# [HNOI2011]括号修复

【出处】

HNOI2011Day1

【题目描述】

1、统一：将[a,b]之间的所有括号改成c（“(”或“)”）

2、翻转：将[a,b]之间的字符串翻转

3、改变：将[a,b]之间的‘(’变成‘)’

4、询问：询问[a,b]之间的字符串至少要改变多少位才能变成合法的括号序列。

N,M≤100000

【算法分析】

1、整个区间——区间对应为根

2、(1,x)——x+1旋到根，区间对应为根的左子树

3、(x,n)——x-1旋到根，区间对应为根的右子树

4、(x,y)——x-1旋到根，接着y+1旋到根的右子树，区间对应为根的右子树的左子树

const
maxn=100000;
var
n,m,i,j,k,p,x,y,root,tmp:longint;c:char;str:string;
rev,en:array[0..maxn] of boolean;
l,r,fa,sum,s,size,sa,xl,xr,yl,yr,satime,entime:array[0..maxn] of longint;
begin
repeat
if c=' ' then break;
until eoln;
end;

begin
repeat
if c=' ' then break;
until eoln;
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure prev(i:longint);
begin
rev[i]:=not rev[i];
tmp:=xl[i];xl[i]:=xr[i];xr[i]:=tmp;
tmp:=yl[i];yl[i]:=yr[i];yr[i]:=tmp;
tmp:=l[i];l[i]:=r[i];r[i]:=tmp;
end;
procedure psa(i,t,time:longint);
begin
satime[i]:=time;
sa[i]:=t;
s[i]:=t;
sum[i]:=t*size[i];
if t=1 then begin xl[i]:=sum[i];xr[i]:=sum[i];yl[i]:=0;yr[i]:=0;end
else begin xl[i]:=0;xr[i]:=0;yl[i]:=-sum[i];yr[i]:=-sum[i];end;
end;

procedure pen(i,time:longint);
begin
if (satime[i]>0)and(satime[i]<time) then
begin
en[i]:=false;
psa(i,-sa[i],time);
exit;
end;

entime[i]:=time;
en[i]:=not en[i];
s[i]:=-s[i];
sum[i]:=-sum[i];
tmp:=xl[i];xl[i]:=yl[i];yl[i]:=tmp;
tmp:=xr[i];xr[i]:=yr[i];yr[i]:=tmp;
end;

procedure pup(i:longint);
begin
size[i]:=size[l[i]]+size[r[i]]+1;
sum[i]:=sum[l[i]]+sum[r[i]]+s[i];
xl[i]:=max(max(xl[l[i]],sum[l[i]]+s[i]+xl[r[i]]),0);
xr[i]:=max(max(xr[r[i]],sum[r[i]]+s[i]+xr[l[i]]),0);
yl[i]:=max(max(yl[l[i]],-sum[l[i]]-s[i]+yl[r[i]]),0);
yr[i]:=max(max(yr[r[i]],-sum[r[i]]-s[i]+yr[l[i]]),0);
end;
procedure pdown(i:longint);
begin
if rev[i] then
begin
if l[i]>0 then prev(l[i]);
if r[i]>0 then prev(r[i]);
rev[i]:=false;
end;

if en[i] then
begin
pen(l[i],entime[i]);
pen(r[i],entime[i]);
en[i]:=false;
entime[i]:=0;
end;

if sa[i]<>0 then
begin
if l[i]>0 then psa(l[i],sa[i],satime[i]);
if r[i]>0 then psa(r[i],sa[i],satime[i]);
sa[i]:=0;
satime[i]:=0;
end;
end;
procedure left(i:longint);
var x,y:longint;
begin
x:=r[i];
y:=l[x];
r[i]:=y;
if y>0 then fa[y]:=i;
if fa[i]>0 then
if l[fa[i]]=i then l[fa[i]]:=x else r[fa[i]]:=x;
fa[x]:=fa[i];
l[x]:=i;
fa[i]:=x;
pup(i);
if i=root then root:=x;
end;

procedure right(i:longint);
var x,y:longint;
begin
x:=l[i];
y:=r[x];
l[i]:=y;
if y>0 then fa[y]:=i;
if fa[i]>0 then
if l[fa[i]]=i then l[fa[i]]:=x else r[fa[i]]:=x;
fa[x]:=fa[i];
r[x]:=i;
fa[i]:=x;
pup(i);
if i=root then root:=x;
end;

procedure splay(x,f:longint);
var y,z:longint;
begin
pdown(x);
while fa[x]<>f do
begin
y:=fa[x];
z:=fa[y];
if z>0 then pdown(z);
if y>0 then pdown(y);
if z=f then
if l[y]=x then right(y) else left(y)
else
if l[z]=y then
if l[y]=x then begin right(z);right(y);end
else begin left(y);right(z);end
else
if l[y]=x then begin right(y);left(z);end
else begin left(z);left(y);end;
end;
pup(x);
end;

procedure sel(x,f:longint);
var t:longint;
begin
t:=root;
repeat
pdown(t);
if x=size[l[t]]+1 then break
else
if x<size[l[t]]+1 then t:=l[t]
else begin dec(x,size[l[t]]+1);t:=r[t];end;
until false;
splay(t,f);
end;

function tiqu(x,y:longint):longint;
begin
if x=1 then
if y=n then exit(root)
else begin sel(y+1,0);exit(l[root]);end
else
if y=n then begin sel(x-1,0);exit(r[root]);end
else begin sel(x-1,0);sel(y+1,root);exit(l[r[root]]);end;
end;

procedure build(x,y,f,t:longint);
begin
if f=0 then root:=(x+y) div 2
else
if t=0 then l[f]:=(x+y) div 2 else r[f]:=(x+y) div 2;
fa[(x+y) div 2]:=f;
if x<=(x+y) div 2-1 then build(x,(x+y) div 2-1,(x+y) div 2,0);
if (x+y) div 2+1<=y then build((x+y) div 2+1,y,(x+y) div 2,1);
pup((x+y) div 2);
end;

procedure print(i:longint);
begin
pdown(i);
if l[i]>0 then print(l[i]);
if s[i]=1 then write('(') else write(')');
if r[i]>0 then print(r[i]);
pup(i);
end;
function check:boolean;
var i:longint;
begin
for i:=1 to n do
if (xl[i]<0)or(xr[i]<0)or(yl[i]<0)or(yr[i]<0) then exit(false);
exit(true);
end;

begin
assign(input,'Brackets.in');
assign(output,'Brackets.out');
reset(input);rewrite(output);

for i:=1 to n do
begin
if c='(' then s[i]:=1 else s[i]:=-1;
end;

build(1,n,0,0);

for i:=1 to m do
begin
p:=tiqu(x,y);
if str='Query' then
begin
writeln((yl[p]+1) div 2+(xr[p]+1) div 2);
end
else
if str='Replace' then
begin
if c='(' then psa(p,1,i) else psa(p,-1,i);
while fa[p]>0 do begin pup(fa[p]);p:=fa[p];end;
end
else
if str='Swap' then
begin
prev(p);
while fa[p]>0 do begin pup(fa[p]);p:=fa[p];end;
end
else
if str='Invert' then
begin
pen(p,i);
while fa[p]>0 do begin pup(fa[p]);p:=fa[p];end;
end;