題意
大概說一下我理解的題意。。。
給你一個長度爲的序列,你可以隨意拋棄一些後綴數字,但必須保證序列至少包含個數字。
問將這個序列分成連續段後,問段的權值和最大值最小爲多少?
思路
二分,dp驗證,線段樹優化
二分答案,表示前個數能分成多少段
轉移:
權值線段樹維護前綴和值對應的最大值,支持單點更新,區間查詢即可。
比賽時最初在想,因爲之前剛做過HDU - 1024這個最大子段和,然後自閉了好久不會優化複雜度。。
後來隊友說了句二分,感覺好有道理。。。。
經過一段時間的自閉,感覺好像知道怎麼寫了,想到了dp驗證,線段樹優化。。。but我沒想到權值線段樹,我想成了每個位置維護一個前綴和值和dp權值。。。。然後gg了,比賽代碼如下(不過我當時dp寫法不一樣,思路差不多
AC_Code
vector<LL> vs;
int ok(LL x) {
vs.eb(-1e18);
for(int i = 1; i <= n; ++i) {
res[i] = res[i-1] + ar[i];
vs.eb(res[i]), vs.eb(res[i] - x);
}
my_unique(vs);
build(1, vs.size(), 1);
int flag = 0;
for(int i = 1; i <= n; ++i) {
if(res[i] <= x) dp[i] = 1;
else dp[i] = 0;
int tmp = lower_bound(all(vs), res[i]) - vs.begin();
int las = lower_bound(all(vs), res[i] - x) - vs.begin();
int ret = query(las, vs.size(), 1, vs.size(), 1);
if(ret) dp[i] = big(ret + 1, dp[i]);
update(tmp, dp[i], 1, vs.size(), 1);
flag = max(flag, dp[i]);
}
vs.clear();
return flag >= k;
}