問題描述
這幾天lotus對培養盆栽很感興趣,於是她想搭建乙個溫室來滿足她的研究慾望。輸入描述lotus將所有的n
n株盆栽都放在新建的溫室裡,所以所有盆栽都處於完全相同的環境中。
每一株盆栽都有乙個最佳生長溫度區間[l,r][l
,r],在這個範圍的溫度下生長會生長得最好,但是不一定會提供最佳的研究價值(lotus認為研究發育不良的盆栽也是很有研究價值的)。
lotus進行了若干次試驗,發現若第i
i株盆栽的生長溫度適宜,可以提供a_ia
i的研究價值;若生長溫度超過了適宜溫度的上限,能提供b_ib
i的研究價值;若生長溫度低於適宜溫度的下限,則能提供c_ic
i的研究價值。
現在通過試驗,lotus已經得知了每一株盆栽的適宜生長溫度範圍,也知道了它們的aa、b
b、cc的值。你需要根據這些資訊,給溫室選定乙個溫度(這個溫度可以是任意實數),使得lotus能獲得的研究價值最大。
多組資料,第一行乙個整數t輸出描述t表示資料組數
每組資料第一行乙個整數n\in[1,50000]n∈
[1,5
0000
],表示盆栽數量
接下來n
n行每行五個整數l_i,r_i,a_i,b_i,c_i\in[1, 10^9]l
i,
ri
,a
i,
bi
,c
i∈
[1,1
09
],意義如上所述
每組資料輸出一行乙個整數表示答案輸入樣例
1輸出樣例55 8 16 20 12
10 16 3 13 13
8 11 13 1 11
7 9 6 17 5
2 11 20 8 5
83
這題我寫的方法有點蠢。
我是列舉所有邊界的座標,因為一開始我就認為這樣列舉,就可以包含所有情況,事實上這樣是錯的。比如兩個區間[1,2]和[3,4],我只會列舉1,2,3,4這四個點,但是很顯然還有溫度是3.5的情況沒有考慮到,所以後來我直接把上下界排好序後,把相鄰兩個邊界的中點也作為列舉的物件。
對於每乙個列舉的溫度t,我們只需要考慮三個部分:
1. 有多少個區間的右端點r在比t小,對於這些區間來說,溫度比適宜的高,研究價值為b。
2. 有多少個區間的右端點l在比t大,對於這些區間來說,溫度比適宜的低,研究價值為c。
3. 除了1和2所包括的區間,剩下的區間就是滿足適宜條件的,研究價值為a。
顯然上面三個部分互相不會重複,那麼需要解決的問題就是,列舉之後如何快速計算上面的結果。
可以感覺到1和2能用二分來計算。首先我們要把所有的區間按左端點排序存起來lx,接著按右端點排序存起來rx。
對於lx,預處理出乙個a的字首和sumal和乙個c的字首和sumc。
對於rx,預處理出乙個a的字首和sumar和乙個b的字首和sumb。
然後每次列舉溫度t,找到lx中比t大的位置以及rx中比t小的位置,然後用a的總和suma減去這兩部分的a的總價值,再加上第一段的c的價值和和第二段的b的價值和即可。
思路不像官方題解中那麼好寫,具體看**。
#include using namespace std;
const int maxn = 50005;
struct node
}l[maxn], r[maxn];
long long a[maxn], b[maxn], c[maxn];
long long sumal[maxn], sumar[maxn], sumb[maxn], sumc[maxn];
double lx[maxn], rx[maxn];
int main() ;
r[i] = (node) ;
vec.push_back(ll); vec.push_back(rr);
}sort (l + 1, l + 1 + n);
sort (r + 1, r + 1 + n);
long long suma = 0;
for (int i = 1; i <= n; i++) suma += a[i];
for (int i = 1; i <= n; i++)
for (int i = 1; i <= n; i++)
for (int i = 1; i <= n; i++) lx[i] = l[i].x;
for (int i = 1; i <= n; i++) rx[i] = r[i].x;
long long ans = 0;
sort (vec.begin(), vec.end());
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );
int cnt = vec.size();
for (int i = 1; i < cnt; i++)
vec.push_back((vec[i] + vec[i - 1]) / 2.0);
sort (vec.begin(), vec.end());
cnt = vec.size();
for (int i = 0; i < cnt; i++)
ans = max(ans, max(sumb[n], sumc[n]));
printf("%i64d\n", ans);
}return 0;
}
hdu 5265 二分 列舉
解題思路 首先對每個數進行去模,這樣得到的數就會是 0,p 1 的範圍,接下來就是如何組合的問題了。這裡要考慮到模的性質了,假設取的兩個數分別為i,j,其中i j,如果當前數i p 1 2,那麼就會出現兩種情況 1 j p 1 2,這樣算出來的結果必定是i j p,i和j肯定都要盡可能大 2 j p...
瘋牛(二分列舉)
描述 農夫 john 建造了一座很長的畜欄,它包括n 2 n 100,000 個隔間,這些小隔間依次編號為x1,xn 0 xi 1,000,000,000 但是,john的c 2 c n 頭牛們並不喜歡這種布局,而且幾頭牛放在乙個隔間裡,他們就要發生爭鬥。為了不讓牛互相傷害。john決定自己給牛分配...
poj 3273 二分列舉
題意 給出乙個有n個資料的陣列,將其分為連續的m份,找到一種分法,是的m份中最大乙份總和最小 參考部落格 題解 一種方案中最大的那部分總和num存在乙個範圍,num總大於等於陣列中最大的那個數,總小於等於整個陣列的和。得到了乙個範圍a b,用二分法不斷縮小範圍,比如第一次取mid a a b 2,那...