好题,这道题可以用线段树来快速模拟费用流寻找最长增广路

这样修改怎么做也很显然了

  1 type node=record
  2        s,lx,rx,mx,lp,rp,pb,pe:longint;
  3      end;
  4 
  5 var tree:array[0..100010*4,0..1] of node;
  6     rev:array[0..100010*4] of boolean;
  7     a:array[0..100010] of longint;
  8     q:array[0..100010] of node;
  9     j,t,ans,i,n,m,x,y,k,ch:longint;
 10     c:node;
 11 
 12 procedure swap(var a,b:node);
 13   var c:node;
 14   begin
 15     c:=a;
 16     a:=b;
 17     b:=c;
 18   end;
 19 
 20 procedure put(var a:node; x:longint);
 21   begin
 22     a.lx:=x;
 23     a.rx:=x;
 24     a.mx:=x;
 25     a.s:=x;
 26   end;
 27 
 28 procedure update(var c:node; a,b:node);
 29   begin
 30     c.s:=a.s+b.s;
 31     c.lx:=a.lx; c.lp:=a.lp;
 32     if a.s+b.lx>c.lx then
 33     begin
 34       c.lx:=a.s+b.lx;
 35       c.lp:=b.lp;
 36     end;
 37     c.rx:=b.rx; c.rp:=b.rp;
 38     if b.s+a.rx>c.rx then
 39     begin
 40       c.rx:=b.s+a.rx;
 41       c.rp:=a.rp;
 42     end;
 43 
 44     c.mx:=a.rx+b.lx; c.pb:=a.rp; c.pe:=b.lp;  //这里要维护位置,相当于记录增广路的起点终点
 45     if c.mx<a.mx then
 46     begin
 47       c.mx:=a.mx;
 48       c.pb:=a.pb;
 49       c.pe:=a.pe;
 50     end;
 51     if c.mx<b.mx then
 52     begin
 53       c.mx:=b.mx;
 54       c.pb:=b.pb;
 55       c.pe:=b.pe;
 56     end;
 57   end;
 58 
 59 procedure build(i,l,r:longint);
 60   var m,j:longint;
 61   begin
 62     if l=r then
 63     begin
 64       put(tree[i,1],a[l]);
 65       put(tree[i,0],-a[l]);
 66       for j:=0 to 1 do
 67       begin
 68         tree[i,j].lp:=l;
 69         tree[i,j].rp:=l;
 70         tree[i,j].pb:=l;
 71         tree[i,j].pe:=l;
 72       end;
 73     end
 74     else begin
 75       m:=(l+r) shr 1;
 76       build(i*2,l,m);
 77       build(i*2+1,m+1,r);
 78       update(tree[i,1],tree[i*2,1],tree[i*2+1,1]);
 79       update(tree[i,0],tree[i*2,0],tree[i*2+1,0]);
 80     end;
 81   end;
 82 
 83 procedure change(i:longint);
 84   begin
 85     swap(tree[i,0],tree[i,1]);
 86     rev[i]:=not rev[i];
 87   end;
 88 
 89 procedure push(i:longint);
 90   begin
 91     rev[i]:=false;
 92     change(i*2);
 93     change(i*2+1);
 94   end;
 95 
 96 procedure work(i,l,r:longint);
 97   var m:longint;
 98   begin
 99     if l=r then
100     begin
101       put(tree[i,1],y);  //一条边和它的反向弧
102       put(tree[i,0],-y);
103     end
104     else begin
105       m:=(l+r) shr 1;
106       if rev[i] then push(i);
107       if x<=m then work(i*2,l,m)
108       else work(i*2+1,m+1,r);
109       update(tree[i,1],tree[i*2,1],tree[i*2+1,1]);
110       update(tree[i,0],tree[i*2,0],tree[i*2+1,0]);
111     end;
112   end;
113 
114 function ask(i,l,r:longint):node;
115   var m:longint;
116       s,s1,s2:node;
117   begin
118     if (x<=l) and (y>=r) then exit(tree[i,1])
119     else begin
120       m:=(l+r) shr 1;
121       if rev[i] then push(i);
122       if y<=m then exit(ask(i*2,l,m));
123       if x>m then exit(ask(i*2+1,m+1,r));
124       s1:=ask(i*2,l,m);
125       s2:=ask(i*2+1,m+1,r);
126       update(s,s1,s2);
127       exit(s);
128     end;
129   end;
130 
131 procedure rever(i,l,r,x,y:longint);  //翻转,因为图的特殊性可知
132   var m:longint;
133   begin
134     if (x<=l) and (y>=r) then change(i)
135     else begin
136       m:=(l+r) shr 1;
137       if rev[i] then push(i);
138       if x<=m then rever(i*2,l,m,x,y);
139       if y>m then rever(i*2+1,m+1,r,x,y);
140       update(tree[i,1],tree[i*2,1],tree[i*2+1,1]);
141       update(tree[i,0],tree[i*2,0],tree[i*2+1,0]);
142     end;
143   end;
144 
145 begin
146   readln(n);
147   for i:=1 to n do
148     read(a[i]);
149   build(1,1,n);
150   readln(m);
151   for i:=1 to m do
152   begin
153     read(ch);
154     if ch=1 then
155     begin
156       readln(x,y,k);
157       ans:=0;
158       t:=0;
159       for j:=1 to k do
160       begin
161         c:=ask(1,1,n);
162         if c.mx>0 then ans:=ans+c.mx
163         else break;
164         rever(1,1,n,c.pb,c.pe);
165         inc(t);
166         q[t]:=c;
167       end;
168       for j:=t downto 1 do
169         rever(1,1,n,q[j].pb,q[j].pe);
170       writeln(ans);
171     end
172     else begin
173       readln(x,y);
174       work(1,1,n);
175     end;
176   end;
177 end.
View Code

 

posted on 2015-06-04 22:17  acphile  阅读(241)  评论(0编辑  收藏  举报