BZOJ1858: [Scoi2010]序列操作
2014-08-10 12:35
363 查看
1858: [Scoi2010]序列操作
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1068 Solved: 545
[Submit][Status]
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 100 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
52
6
5
HINT
对于30%的数据,1<=n, m<=1000对于100%的数据,1<=n, m<=100000
Source
Day2这题的区间合并实在太恶心了,写完我都快吐了。。。那天过来再调吧。。。
代码:
{$inline on} {$M 1000000000,0,maxlongint} const maxn=100000+1000; var s,sum1,sum0,v,lx0,rx0,lx1,rx1,mx0,mx1,fa,id,a:array[0..maxn] of longint; rev,tag:array[0..maxn] of boolean; c:array[0..maxn,0..1] of longint; i,n,m,x,y,z,rt,ch,ll,rr:longint; procedure swap(var x,y:longint);inline; var t:longint; begin t:=x;x:=y;y:=t; end; function max(x,y:longint):longint;inline; begin if x>y then exit(x) else exit(y); end; procedure pushup(x:longint); var l,r:longint; begin l:=c[x,0];r:=c[x,1]; s[x]:=s[l]+s[r]+1; sum1[x]:=sum1[l]+sum1[r]+ord(v[x]=1); sum0[x]:=sum0[l]+sum0[r]+ord(v[x]=0); if lx0[l]=s[l] then begin if v[x]=0 then lx0[x]:=s[l]+1+lx0[r] else lx0[x]:=s[l]; end else lx0[x]:=lx0[l]; if rx0[r]=s[r] then begin if v[x]=0 then rx0[x]:=s[r]+1+rx0[l] else rx0[x]:=s[r]; end; if lx1[l]=s[l] then begin if v[x]=1 then lx1[x]:=s[l]+1+lx1[r] else lx1[x]:=s[l]; end else lx1[x]:=lx1[l]; if rx1[r]=s[r] then begin if v[x]=1 then rx1[x]:=s[r]+1+rx1[l] else rx1[x]:=s[r]; end; mx0[x]:=max(mx0[l],mx0[r]); if v[x]=0 then mx0[x]:=max(mx0[x],rx0[l]+lx0[r]+1); mx1[x]:=max(mx1[l],mx1[r]); if v[x]=1 then mx1[x]:=max(mx1[x],rx1[l]+lx1[r]+1); end; procedure rotate(x:longint;var k:longint); var y,z,l,r:longint; begin y:=fa[x];z:=fa[y]; l:=ord(c[y,1]=x);r:=l xor 1; if y=k then k:=x else c[z,ord(c[z,1]=y)]:=x; fa[x]:=z;fa[y]:=x;fa[c[x,r]]:=y; c[y,l]:=c[x,r];c[x,r]:=y; pushup(y);pushup(x); end; procedure splay(x:longint;var k:longint); var y,z:longint; begin while x<>k do begin y:=fa[x];z:=fa[y]; if y<>k then if (c[z,0]=y) xor (c[y,0]=x) then rotate(x,k) else rotate(y,k); rotate(x,k); end; end; procedure build(l,r,f:longint); var mid,x,y:longint; begin if l>r then exit; mid:=(l+r)>>1; x:=id[mid];y:=id[f]; c[y,ord(mid>f)]:=x;fa[x]:=y; v[x]:=a[mid]; if l=r then begin s[x]:=1;sum0[x]:=ord(v[x]=0);sum1[x]:=ord(v[x]=1); lx0:=sum0;rx0:=sum0;mx0:=sum0; lx1:=sum1;rx1:=sum1;mx1:=sum1; exit; end; build(l,mid-1,mid);build(mid+1,r,mid); pushup(x); end; procedure init; begin readln(n,m); a[1]:=-1;a[n+2]:=-1; for i:=2 to n+1 do read(a[i]);readln; for i:=1 to n+2 do id[i]:=i; build(1,n+2,0);rt:=(n+3)>>1; end; procedure same0(x:longint); begin tag[x]:=true;v[x]:=0; sum0[x]:=s[x];lx0[x]:=s[x];rx0[x]:=s[x];mx0[x]:=s[x]; sum1[x]:=0;lx1[x]:=0;rx1[x]:=0;mx1[x]:=0; end; procedure same1(x:longint); begin tag[x]:=true;v[x]:=1; sum1[x]:=s[x];lx1[x]:=s[x];rx1[x]:=s[x];mx1[x]:=s[x]; sum0[x]:=0;lx0[x]:=0;rx0[x]:=0;mx0[x]:=0; end; procedure rever(x:longint); begin if (x=0) or (tag[x]) then exit; rev[x]:=not(rev[x]);v[x]:=v[x] xor 1; swap(lx0[x],lx1[x]); swap(rx0[x],rx1[x]); swap(sum0[x],sum1[x]); swap(mx0[x],mx1[x]); end; procedure pushdown(x:longint); var l,r:longint; begin l:=c[x,0];r:=c[x,1]; if tag[x] then begin tag[x]:=false;rev[x]:=false; if v[x]=0 then begin same0(l);same0(r);end else begin same1(l);same1(r);end; end; if rev[x] then begin rev[x]:=false; rever(l);rever(r); pushup(x); end; end; function find(x,rk:longint):longint; var l,r:longint; begin pushdown(x);l:=c[x,0];r:=c[x,1]; if s[l]+1=rk then exit(x) else if s[l]>=rk then exit(find(l,rk)) else exit(find(r,rk-s[l]-1)); end; procedure split(l,r:longint;var x,y:longint); begin x:=find(rt,l);y:=find(rt,r); splay(x,rt);splay(y,c[x,1]); end; procedure main; begin for i:=1 to m do begin readln(ch,ll,rr);inc(ch);inc(ll,1);inc(rr,3); split(ll,rr,x,y); case ch of 1:same0(c[y,0]); 2:same1(c[y,0]); 3:rever(c[y,0]); 4:writeln(sum1[c[y,0]]); 5:writeln(mx1[c[y,0]]); end; end; end; begin assign(input,'input.txt');assign(output,'output.txt'); reset(input);rewrite(output); init; main; close(input);close(output); end.
View Code
UPD:这是一份错的代码。。。
正解戳这里额:/article/6822595.html
相关文章推荐
- bzoj 1858: [Scoi2010]序列操作(线段树)
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
- 【BZOJ1858】【SCOI2010】序列操作(线段树+合并)
- 【BZOJ1858】[Scoi2010]序列操作【线段树】
- bzoj 1858: [Scoi2010]序列操作 线段树
- bzoj1858: [Scoi2010]序列操作
- BZOJ 1858 SCOI2010 序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 [线段树]
- 【BZOJ 1858】【SCOI 2010】序列操作【区间线段树】
- bzoj1858 [Scoi2010]序列操作
- 【BZOJ 1858】 [Scoi2010]序列操作
- bzoj1858: [Scoi2010]序列操作
- bzoj1858【scoi2010】序列操作
- bzoj 1858: [Scoi2010]序列操作 -- 线段树
- BZOJ 1858 SCOI2010 序列操作 线段树
- 【bzoj 1858】 [Scoi2010]序列操作 线段树
- bzoj 1858: [Scoi2010] 序列操作 题解
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
- [BZOJ 1858][Scoi2010]序列操作(线段树)
- 【BZOJ1858】[Scoi2010]序列操作 线段树