首页 > 代码库 > bzoj1858 [Scoi2010]序列操作

bzoj1858 [Scoi2010]序列操作

Description

lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

Input

输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目 第二行包括n个数,表示序列的初始状态 接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作="" <="" div="">

Output

对于每一个询问操作,输出一行,包括1个数,表示其对应的答案

Sample Input

10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9

Sample Output

5
2
6
5

HINT

对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000

Source

Day2

 

 

看出来简单、写起来有点复杂的线段树,有不少要注意的地方。

表示这是我码过的最长的线段树。

  1 program rrr(input,output);
  2 type
  3   treetype=record
  4      l,r,l0,r0,l1,r1,sum,m0,m1,t:longint;
  5   end;
  6 var
  7   a:array[0..400040]of treetype;
  8   c:array[0..100010]of longint;
  9   n,m,op,x,y,t,i:longint;
 10 procedure swap(var a,b:longint);
 11 begin
 12    t:=a;a:=b;b:=t;
 13 end;
 14 function min(a,b:longint):longint;
 15 begin
 16    if a<b then exit(a) else exit(b);
 17 end;
 18 function max(a,b:longint):longint;
 19 begin
 20    if a>b then exit(a) else exit(b);
 21 end;
 22 procedure unite(x,y,k:longint);
 23 begin
 24    a[k].sum:=a[x].sum+a[y].sum;
 25    if a[x].l0=a[x].r-a[x].l+1 then a[k].l0:=a[x].l0+a[y].l0 else a[k].l0:=a[x].l0;
 26    if a[y].r0=a[y].r-a[y].l+1 then a[k].r0:=a[x].r0+a[y].r0 else a[k].r0:=a[y].r0;
 27    if a[x].l1=a[x].r-a[x].l+1 then a[k].l1:=a[x].l1+a[y].l1 else a[k].l1:=a[x].l1;
 28    if a[y].r1=a[y].r-a[y].l+1 then a[k].r1:=a[x].r1+a[y].r1 else a[k].r1:=a[y].r1;
 29    if a[x].m0>a[y].m0 then a[k].m0:=a[x].m0 else a[k].m0:=a[y].m0;
 30    if a[x].r0+a[y].l0>a[k].m0 then a[k].m0:=a[x].r0+a[y].l0;
 31    if a[x].m1>a[y].m1 then a[k].m1:=a[x].m1 else a[k].m1:=a[y].m1;
 32    if a[x].r1+a[y].l1>a[k].m1 then a[k].m1:=a[x].r1+a[y].l1;
 33 end;
 34 procedure build(k,l,r:longint);
 35 var
 36   mid,i:longint;
 37 begin
 38    a[k].l:=l;a[k].r:=r;a[k].t:=-1;
 39    if l=r then
 40       begin
 41          if c[l]=0 then begin a[k].l0:=1;a[k].r0:=1;a[k].l1:=0;a[k].r1:=0;a[k].sum:=0;a[k].m0:=1;a[k].m1:=0; end
 42          else begin a[k].l0:=0;a[k].r0:=0;a[k].l1:=1;a[k].r1:=1;a[k].sum:=1;a[k].m0:=0;a[k].m1:=1; end;
 43          exit;
 44       end;
 45    mid:=(l+r)>>1;i:=k+k;
 46    build(i,l,mid);build(i+1,mid+1,r);
 47    unite(i,i+1,k);
 48 end;
 49 procedure pushdown(k:longint);
 50 var
 51   x,y:longint;
 52 begin
 53    if a[k].l=a[k].r then a[k].t:=-1;
 54    if a[k].t=-1 then exit;
 55    x:=k+k;y:=k+k+1;
 56    if a[k].t=1 then
 57       begin
 58          a[x].sum:=a[x].r-a[x].l+1;a[y].sum:=a[y].r-a[y].l+1;
 59          a[x].l0:=0;a[x].r0:=0;a[x].l1:=a[x].sum;a[x].r1:=a[x].sum;a[x].m0:=0;a[x].m1:=a[x].sum;
 60          a[y].l0:=0;a[y].r0:=0;a[y].l1:=a[y].sum;a[y].r1:=a[y].sum;a[y].m0:=0;a[y].m1:=a[y].sum;
 61          a[x].t:=1;a[y].t:=1;
 62       end
 63    else if a[k].t=0 then
 64       begin
 65          a[x].sum:=0;a[y].sum:=0;
 66          t:=a[x].r-a[x].l+1;a[x].l0:=t;a[x].r0:=t;a[x].l1:=0;a[x].r1:=0;a[x].m0:=t;a[x].m1:=0;
 67          t:=a[y].r-a[y].l+1;a[y].l0:=t;a[y].r0:=t;a[y].l1:=0;a[y].r1:=0;a[y].m0:=t;a[y].m1:=0;
 68          a[x].t:=0;a[y].t:=0;
 69       end
 70    else
 71       begin
 72          a[x].sum:=a[x].r-a[x].l+1-a[x].sum;a[y].sum:=a[y].r-a[y].l+1-a[y].sum;
 73          swap(a[x].l0,a[x].l1);swap(a[x].r0,a[x].r1);swap(a[x].m0,a[x].m1);
 74          swap(a[y].l0,a[y].l1);swap(a[y].r0,a[y].r1);swap(a[y].m0,a[y].m1);
 75          case a[x].t of
 76             0:a[x].t:=1;
 77             1:a[x].t:=0;
 78             2:a[x].t:=-1;
 79             -1:a[x].t:=2;
 80          end;
 81          case a[y].t of
 82             0:a[y].t:=1;
 83             1:a[y].t:=0;
 84             2:a[y].t:=-1;
 85             -1:a[y].t:=2;
 86          end;
 87       end;
 88    a[k].t:=-1;
 89 end;
 90 procedure change(k:longint);
 91 var
 92   mid,i:longint;
 93 begin
 94    pushdown(k);
 95    if (x<=a[k].l) and (a[k].r<=y) then
 96       begin
 97          t:=a[k].r-a[k].l+1;
 98          if op=0 then begin a[k].sum:=0;a[k].l0:=t;a[k].r0:=t;a[k].l1:=0;a[k].r1:=0;a[k].m0:=t;a[k].m1:=0;a[k].t:=0; end
 99          else begin a[k].sum:=t;a[k].l0:=0;a[k].r0:=0;a[k].l1:=t;a[k].r1:=t;a[k].m0:=0;a[k].m1:=t;a[k].t:=1; end;
100          exit;
101       end;
102    mid:=(a[k].l+a[k].r)>>1;i:=k+k;
103    if x<=mid then change(i);
104    if mid<y then change(i+1);
105    unite(i,i+1,k);
106 end;
107 procedure changef(k:longint);
108 var
109   mid,i:longint;
110 begin
111    pushdown(k);
112    if (x<=a[k].l) and (a[k].r<=y) then
113       begin
114          swap(a[k].l0,a[k].l1);swap(a[k].r0,a[k].r1);swap(a[k].m0,a[k].m1);a[k].sum:=a[k].r-a[k].l+1-a[k].sum;a[k].t:=2;
115          exit;
116       end;
117    mid:=(a[k].l+a[k].r)>>1;i:=k+k;
118    if x<=mid then changef(i);
119    if mid<y then changef(i+1);
120    unite(i,i+1,k);
121 end;
122 function asksum(k:longint):longint;
123 var
124   mid,ans:longint;
125 begin
126    pushdown(k);
127    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum);
128    mid:=(a[k].l+a[k].r)>>1;ans:=0;
129    if x<=mid then ans:=asksum(k+k);
130    if mid<y then ans:=ans+asksum(k+k+1);
131    exit(ans);
132 end;
133 function query(k:longint):longint;
134 var
135   mid,ans,i:longint;
136 begin
137    pushdown(k);
138    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].m1);
139    mid:=(a[k].l+a[k].r)>>1;ans:=0;i:=k+k;
140    if x<=mid then ans:=query(i);
141    if mid<y then ans:=max(ans,query(i+1));
142    if (x<=mid) and (mid<y) then ans:=max(ans,min(a[i].r-x+1,a[i].r1)+min(y-a[i+1].l+1,a[i+1].l1));
143    exit(ans);
144 end;
145 begin
146    assign(input,r.in);assign(output,r.out);reset(input);rewrite(output);
147    readln(n,m);
148    for i:=1 to n do read(c[i]);
149    build(1,1,n);
150    for i:=1 to m do
151       begin
152          readln(op,x,y);inc(x);inc(y);
153          if (op=0) or (op=1) then change(1)
154          else if op=2 then changef(1)
155          else if op=3 then writeln(asksum(1))
156          else writeln(query(1));
157       end;
158    close(input);close(output);
159 end.

 

bzoj1858 [Scoi2010]序列操作