[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 }

 

posted @ 2019-02-11 08:23  HocRiser  阅读(420)  评论(0编辑  收藏  举报