[BZOJ3638 && BZOJ3272]带修区间不相交最大K子段和(线段树模拟费用流)
https://www.cnblogs.com/DaD3zZ-Beyonder/p/5634149.html
k可重区间集问题有两种建图方式,可能这一种才可以被线段树优化。
换个角度看,这也是一个类似[BZOJ1150]数据备份的可撤销贪心。
1 #include<cstdio> 2 #include<algorithm> 3 #define ls (x<<1) 4 #define rs (ls|1) 5 #define lson ls,L,mid 6 #define rson rs,mid+1,R 7 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 8 using namespace std; 9 10 const int N=100010; 11 int n,T,x,y,l,r,k,op,ans,top,a[N]; 12 struct Tr{ int lx,rx,mx,sm,pl,pr,p1,p2; }; 13 struct P{ Tr mx,mn; int tag; }v[N<<2]; 14 struct S{ int l,r; }stk[N]; 15 16 Tr merge(const Tr &lc,const Tr &rc){ 17 Tr c; c.sm=lc.sm+rc.sm; 18 c.lx=lc.sm+rc.lx>lc.lx? lc.sm+rc.lx : lc.lx; 19 c.pl=lc.sm+rc.lx>lc.lx? rc.pl : lc.pl; 20 c.rx=rc.sm+lc.rx>rc.rx? rc.sm+lc.rx : rc.rx; 21 c.pr=rc.sm+lc.rx>rc.rx? lc.pr : rc.pr; 22 c.mx=lc.rx+rc.lx; c.p1=lc.pr; c.p2=rc.pl; 23 if (c.mx<lc.mx) c.mx=lc.mx,c.p1=lc.p1,c.p2=lc.p2; 24 if (c.mx<rc.mx) c.mx=rc.mx,c.p1=rc.p1,c.p2=rc.p2; 25 return c; 26 } 27 28 void upd(int x){ 29 v[x].mn=merge(v[ls].mn,v[rs].mn); 30 v[x].mx=merge(v[ls].mx,v[rs].mx); 31 } 32 33 void push(int x){ 34 if (!v[x].tag) return; 35 v[x].tag^=1; 36 swap(v[ls].mx,v[ls].mn); v[ls].tag^=1; 37 swap(v[rs].mx,v[rs].mn); v[rs].tag^=1; 38 } 39 40 void put(int x,int p,int k){ 41 v[x].mx=(Tr){k,k,k,k,p,p,p,p}; 42 v[x].mn=(Tr){-k,-k,-k,-k,p,p,p,p}; 43 } 44 45 void build(int x,int L,int R){ 46 if (L==R){ put(x,L,a[L]); return; } 47 int mid=(L+R)>>1; 48 build(lson); build(rson); upd(x); 49 } 50 51 void mdf(int x,int L,int R,int pos,int k){ 52 if (L==R){ put(x,pos,k); return; } 53 int mid=(L+R)>>1; push(x); 54 if (pos<=mid) mdf(lson,pos,k); else mdf(rson,pos,k); 55 upd(x); 56 } 57 58 Tr que(int x,int L,int R,int l,int r){ 59 if (L==l && r==R) return v[x].mx; 60 int mid=(L+R)>>1; push(x); 61 if (r<=mid) return que(lson,l,r); 62 else if (l>mid) return que(rson,l,r); 63 else return merge(que(lson,l,mid),que(rson,mid+1,r)); 64 } 65 66 void rev(int x,int L,int R,int l,int r){ 67 if (L==l && r==R){ swap(v[x].mn,v[x].mx); v[x].tag^=1; return; } 68 int mid=(L+R)>>1; push(x); 69 if (r<=mid) rev(lson,l,r); 70 else if (l>mid) rev(rson,l,r); 71 else rev(lson,l,mid),rev(rson,mid+1,r); 72 upd(x); 73 } 74 75 void solve(int l,int r,int k){ 76 ans=0; top=0; 77 while (k--){ 78 Tr tmp=que(1,1,n,l,r); 79 if (tmp.mx>0) ans+=tmp.mx; else break; 80 rev(1,1,n,tmp.p1,tmp.p2); 81 stk[++top]=(S){tmp.p1,tmp.p2}; 82 } 83 for (int i=top; i; i--) rev(1,1,n,stk[i].l,stk[i].r); 84 printf("%d\n",ans); 85 } 86 87 int main(){ 88 freopen("bzoj3272.in","r",stdin); 89 freopen("bzoj3272.out","w",stdout); 90 scanf("%d",&n); 91 rep(i,1,n) scanf("%d",&a[i]); 92 build(1,1,n); 93 for (scanf("%d",&T); T--; ){ 94 scanf("%d",&op); 95 if (op==0) scanf("%d%d",&x,&y),mdf(1,1,n,x,y); 96 else scanf("%d%d%d",&l,&r,&k),solve(l,r,k); 97 } 98 return 0; 99 }