[BZOJ1858] [Scoi2010]序列操作

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1858

题目大意

给定一个01序列每次操作
0:[L,R]都变0
1:[L,R]都变1
2:[L,R]0变1,1变0
3:查询[L,R]区间内1个数
4:查询[L,R]区间内最长连续1个数

题解

明显线段树
维护
1.区间和
2.左端点开始连续0个数
3.右端点开始连续0个数
4.最长连续0个数
5.左端点开始连续1个数
6.右端点开始连续1个数
7.最长连续1个数
注意细节细节细节细节细节细节细节细节细节细节细节细节细节细节

const
 maxn=100005;
type
 group=record
  maxx,maxl,maxr:longint;
 end;
var
 w:array[0..8*maxn,1..10]of longint;
 i,j,k:longint;
 a,b,c:longint;
 n,m:longint;
procedure swap(var a,b:longint);
var c:longint;
begin
 c:=a; a:=b; b:=c;
end;

function max(a,b:longint):longint;
begin
 if a>b then exit(a) else exit(b);
end;

procedure pushup(a:longint);
begin
 w[a,3]:=w[a<<1,3]+w[a<<1+1,3];
 w[a,4]:=w[a<<1,4]; if w[a<<1,4]=w[a<<1,2]-w[a<<1,1]+1 then inc(w[a,4],w[a<<1+1,4]);
 w[a,5]:=w[a<<1+1,5]; if w[a<<1+1,5]=w[a<<1+1,2]-w[a<<1+1,1]+1 then inc(w[a,5],w[a<<1,5]);
 w[a,6]:=max(max(w[a<<1,6],w[a<<1+1,6]),w[a<<1,5]+w[a<<1+1,4]);
 w[a,7]:=w[a<<1,7]; if w[a<<1,7]=w[a<<1,2]-w[a<<1,1]+1 then inc(w[a,7],w[a<<1+1,7]);
 w[a,8]:=w[a<<1+1,8]; if w[a<<1+1,8]=w[a<<1+1,2]-w[a<<1+1,1]+1 then inc(w[a,8],w[a<<1,8]);
 w[a,9]:=max(max(w[a<<1,9],w[a<<1+1,9]),w[a<<1,8]+w[a<<1+1,7]);
end;

procedure pushdown(a:longint);
var b,i:longint;
begin
 if w[a,1]=w[a,2] then begin w[a,10]:=-1; exit; end;
 b:=a<<1;
 if w[a,10]=0 then begin
  w[b,10]:=0; w[b,3]:=0; w[b,7]:=0; w[b,8]:=0; w[b,9]:=0; w[b,4]:=w[b,2]-w[b,1]+1; w[b,5]:=w[b,4]; w[b,6]:=w[b,4]; inc(b);
  w[b,10]:=0; w[b,3]:=0; w[b,7]:=0; w[b,8]:=0; w[b,9]:=0; w[b,4]:=w[b,2]-w[b,1]+1; w[b,5]:=w[b,4]; w[b,6]:=w[b,4];
 end;
 if w[a,10]=1 then begin
  w[b,10]:=1; w[b,3]:=w[b,2]-w[b,1]+1; w[b,4]:=0; w[b,5]:=0; w[b,6]:=0; w[b,7]:=w[b,3]; w[b,8]:=w[b,3]; w[b,9]:=w[b,3]; inc(b);
  w[b,10]:=1; w[b,3]:=w[b,2]-w[b,1]+1; w[b,4]:=0; w[b,5]:=0; w[b,6]:=0; w[b,7]:=w[b,3]; w[b,8]:=w[b,3]; w[b,9]:=w[b,3];
 end;
 if w[a,10]=2 then begin
  if w[b,10]=0 then w[b,10]:=1 else if w[b,10]=1 then w[b,10]:=0 else if w[b,10]=2 then w[b,10]:=-1 else if w[b,10]=-1 then w[b,10]:=2;
  w[b,3]:=w[b,2]-w[b,1]+1-w[b,3]; for i:=4 to 6 do swap(w[b,i],w[b,i+3]); inc(b);
  if w[b,10]=0 then w[b,10]:=1 else if w[b,10]=1 then w[b,10]:=0 else if w[b,10]=2 then w[b,10]:=-1 else if w[b,10]=-1 then w[b,10]:=2;
  w[b,3]:=w[b,2]-w[b,1]+1-w[b,3]; for i:=4 to 6 do swap(w[b,i],w[b,i+3]);
 end;
 w[a,10]:=-1;
end;

procedure build(a,l,r:longint);
var mid:longint;
begin
 w[a,1]:=l; w[a,2]:=r; w[a,10]:=-1; for i:=3 to 9 do w[a,i]:=0;
 if l=r then begin
  read(w[a,3]);
  if w[a,3]=0
  then for i:=4 to 6 do w[a,i]:=1
  else for i:=7 to 9 do w[a,i]:=1;
  exit;
 end;
 mid:=(l+r)>>1;
 build(a<<1,l,mid); build(a<<1+1,mid+1,r);
 pushup(a);
end;

procedure update(a,l,r,c:longint);
var mid,b,i:longint;
begin
 if w[a,10]<>-1 then pushdown(a);
 if (l=w[a,1])and(r=w[a,2]) then begin
  w[a,10]:=c; b:=a;
  case c of
  0:begin w[b,10]:=0; w[b,3]:=0; w[b,7]:=0; w[b,8]:=0; w[b,9]:=0; w[b,4]:=w[b,2]-w[b,1]+1; w[b,5]:=w[b,4]; w[b,6]:=w[b,4]; end;
  1:begin w[b,10]:=1; w[b,3]:=w[b,2]-w[b,1]+1; w[b,4]:=0; w[b,5]:=0; w[b,6]:=0; w[b,7]:=w[b,3]; w[b,8]:=w[b,3]; w[b,9]:=w[b,3]; end;
  2:begin w[b,10]:=2; w[b,3]:=w[b,2]-w[b,1]+1-w[b,3]; for i:=4 to 6 do swap(w[b,i],w[b,i+3]); end;
  end;
  exit;
 end;
 mid:=(w[a,1]+w[a,2])>>1;
 if r<=mid then update(a<<1,l,r,c) else
 if l>mid then update(a<<1+1,l,r,c)
 else begin update(a<<1,l,mid,c); update(a<<1+1,mid+1,r,c); end;
 pushup(a);
end;

function query1(a,l,r:longint):longint;
var mid:longint;
begin
 if w[a,10]<>-1 then pushdown(a);
 if (l=w[a,1])and(w[a,2]=r) then exit(w[a,3]);
 mid:=(w[a,1]+w[a,2])>>1;
 if r<=mid then exit(query1(a<<1,l,r)) else
 if l>mid then exit(query1(a<<1+1,l,r))
 else exit(query1(a<<1,l,mid)+query1(a<<1+1,mid+1,r));
end;

function query2(a,l,r:longint):group;
var mid:longint; ans,p,q:group;
begin
 if w[a,10]<>-1 then pushdown(a);
 if (l=w[a,1])and(w[a,2]=r) then begin
  ans.maxx:=w[a,9]; ans.maxl:=w[a,7]; ans.maxr:=w[a,8];
  exit(ans);
 end;
 mid:=(w[a,1]+w[a,2])>>1;
 if r<=mid then exit(query2(a<<1,l,r)) else
 if l>mid then exit(query2(a<<1+1,l,r))
 else begin
  p:=query2(a<<1,l,mid); q:=query2(a<<1+1,mid+1,r);
  ans.maxx:=max(max(p.maxx,q.maxx),p.maxr+q.maxl);
  ans.maxl:=p.maxl; if p.maxl=mid-l+1 then inc(ans.maxl,q.maxl);
  ans.maxr:=q.maxr; if q.maxr=r-mid then inc(ans.maxr,p.maxr);
  exit(ans);
 end;
end;

begin
 assign(input,'operation.in'); assign(output,'operation.out'); reset(input); rewrite(output);
 readln(n,m);
 build(1,1,n);
 for i:=1 to m do
  begin
   readln(a,b,c); inc(b); inc(c);
   if a<=2
   then update(1,b,c,a)
   else if a=3 then writeln(query1(1,b,c))
               else writeln(query2(1,b,c).maxx);
  end;
 close(input); close(output);
end.

你可能感兴趣的:([BZOJ1858] [Scoi2010]序列操作)