BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
(BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=3836
(Codeforces) http://codeforces.com/contest/280/problem/D
題解
似乎是最廣為人知的模擬費用流題目。
線段樹維護DP可以做,但是合并的復雜度是\(O(k^2)\), 會TLE.
考慮做\(k\)次費用流,很容易建出一個圖,中間的邊容量都是1,求的是最大費用。
做費用流的過程,我們每次找一條最長路,然后將其增廣,增廣之后這條路的邊權會取負(因為容量都是\(1\)所以要么正要么負,正反向邊不同時出現)。
所以現在要做的就是每次找出和最大的一段區間然后取負,直到和全都小于\(0\)為止。
線段樹維護最大、最小子段和及其位置即可。
仔細想想,每次給一段區間取負就相當于給這段區間內的元素選或者不選的狀態進行反轉(inverse).
也就相當于費用流的退流(反悔)。
時間復雜度\(O(kn\log n)\).
代碼
BZOJ權限號到期了,所以沒在上面交過。
#include<cstdio> #include<cstdlib> #include<iostream> #include<utility> #include<vector> #define pii pair<int,int> #define mkpr make_pair using namespace std;void read(int &x) {int f=1;x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f; }const int N = 1e5; int a[N+3]; vector<pii > pool; int n,q;struct Data {int sum,mx,mxl,mxr,pl,pr,pml,pmr;Data() {sum = mx = mxl = mxr = pl = pr = pml = pmr = 0;} }; Data operator +(Data x,Data y) {Data ret;ret.sum = x.sum+y.sum;if(x.mxl>x.sum+y.mxl){ret.mxl = x.mxl;ret.pl = x.pl;}else{ret.mxl = x.sum+y.mxl;ret.pl = y.pl;}if(y.mxr>x.mxr+y.sum){ret.mxr = y.mxr;ret.pr = y.pr;}else{ret.mxr = x.mxr+y.sum;ret.pr = x.pr;}if(x.mx>y.mx){ret.mx = x.mx;ret.pml = x.pml; ret.pmr = x.pmr;}else{ret.mx = y.mx;ret.pml = y.pml; ret.pmr = y.pmr;}if(x.mxr+y.mxl>ret.mx){ret.mx = x.mxr+y.mxl;ret.pml = x.pr; ret.pmr = y.pl;}return ret; }struct SegmentTree {struct SgTNode{Data ans0,ans1; int tag;} sgt[(N<<2)+3];void pushup(int u){sgt[u].ans0 = sgt[u<<1].ans0+sgt[u<<1|1].ans0;sgt[u].ans1 = sgt[u<<1].ans1+sgt[u<<1|1].ans1;}void pushdown(int u){if(sgt[u].tag){swap(sgt[u<<1].ans0,sgt[u<<1].ans1);sgt[u<<1].tag ^= 1;swap(sgt[u<<1|1].ans0,sgt[u<<1|1].ans1);sgt[u<<1|1].tag ^= 1;sgt[u].tag = 0;}}void build(int u,int le,int ri){if(le==ri){sgt[u].ans0.sum = sgt[u].ans0.mxl = sgt[u].ans0.mxr = sgt[u].ans0.mx = a[le];sgt[u].ans0.pl = sgt[u].ans0.pr = sgt[u].ans0.pml = sgt[u].ans0.pmr = le;sgt[u].ans1.sum = sgt[u].ans1.mxl = sgt[u].ans1.mxr = sgt[u].ans1.mx = -a[le];sgt[u].ans1.pl = sgt[u].ans1.pr = sgt[u].ans1.pml = sgt[u].ans1.pmr = le;return;}int mid = (le+ri)>>1;build(u<<1,le,mid);build(u<<1|1,mid+1,ri);pushup(u);}void modify(int u,int le,int ri,int pos,int x){if(le==pos && ri==pos){sgt[u].ans0.sum = sgt[u].ans0.mxl = sgt[u].ans0.mxr = sgt[u].ans0.mx = x;sgt[u].ans0.pl = sgt[u].ans0.pr = sgt[u].ans0.pml = sgt[u].ans0.pmr = le;sgt[u].ans1.sum = sgt[u].ans1.mxl = sgt[u].ans1.mxr = sgt[u].ans1.mx = -x;sgt[u].ans1.pl = sgt[u].ans1.pr = sgt[u].ans1.pml = sgt[u].ans1.pmr = le;return;}pushdown(u);int mid = (le+ri)>>1;if(pos<=mid) modify(u<<1,le,mid,pos,x);if(pos>mid) modify(u<<1|1,mid+1,ri,pos,x);pushup(u);}void setoppo(int u,int le,int ri,int lb,int rb){if(le>=lb && ri<=rb){sgt[u].tag ^= 1;swap(sgt[u].ans0,sgt[u].ans1);return;}pushdown(u);int mid = (le+ri)>>1;if(lb<=mid) setoppo(u<<1,le,mid,lb,rb);if(rb>mid) setoppo(u<<1|1,mid+1,ri,lb,rb);pushup(u);}Data query(int u,int le,int ri,int lb,int rb){if(le>=lb && ri<=rb) {return sgt[u].ans0;}pushdown(u);int mid = (le+ri)>>1; Data ret;if(rb<=mid) {ret = query(u<<1,le,mid,lb,rb);}else if(lb>mid) {ret = query(u<<1|1,mid+1,ri,lb,rb);}else {ret = query(u<<1,le,mid,lb,rb)+query(u<<1|1,mid+1,ri,lb,rb);}pushup(u);return ret;} } sgt;int main() {scanf("%d",&n);for(int i=1; i<=n; i++) scanf("%d",&a[i]);sgt.build(1,1,n);scanf("%d",&q);while(q--){int opt; scanf("%d",&opt);if(opt==0){int x,y; scanf("%d%d",&x,&y);a[x] = y; sgt.modify(1,1,n,x,y);}else if(opt==1){int x,y,z; scanf("%d%d%d",&x,&y,&z);int ans = 0;for(int i=1; i<=z; i++){Data cur = sgt.query(1,1,n,x,y); // printf("delta=%d [%d,%d]\n",cur.mx,cur.pml,cur.pmr);if(cur.mx<=0) break;ans += cur.mx;sgt.setoppo(1,1,n,cur.pml,cur.pmr);pool.push_back(mkpr(cur.pml,cur.pmr));}printf("%d\n",ans);for(int i=0; i<pool.size(); i++) {sgt.setoppo(1,1,n,pool[i].first,pool[i].second);}pool.clear();}}return 0; }總結
以上是生活随笔為你收集整理的BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UOJ #455 [UER #8]雪灾与
- 下一篇: BZOJ 4849 [NEERC2016