[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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值