题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2333
题意:
思路:离线处理。首先将所有U操作进行,得到一个DFS序列。那么中间操作都是操作的一段区间。然后用线段树维护就好了。
struct node
{
char op[5];
int x,v;
};
node Q[N];
int f[N];
int get(int x)
{
if(f[x]!=x) f[x]=get(f[x]);
return f[x];
}
int n,m,d[N];
int end[N],next[N],pos[N];
void init()
{
RD(n);
int i,x,y;
FOR1(i,n) RD(d[i]);
FOR1(i,n) end[i]=next[i]=f[i]=i;
RD(m);
FOR1(i,m)
{
RD(Q[i].op);
if(Q[i].op[0]=='U')
{
RD(Q[i].x,Q[i].v);
x=get(Q[i].x);
y=get(Q[i].v);
if(x>y) swap(x,y);
f[y]=x;
next[end[x]]=y;
end[x]=end[y];
}
else if(Q[i].op[0]=='F')
{
if(Q[i].op[1]!='3') RD(Q[i].x);
}
else
{
if(Q[i].op[1]=='3') RD(Q[i].x);
else RD(Q[i].x,Q[i].v);
}
}
clr(end,0);
int cnt=0;
FOR1(i,n)
{
x=i;
while(!end[x])
{
pos[x]=end[x]=++cnt;
f[x]=x;
x=next[x];
}
}
FOR1(i,n) next[i]=d[i];
FOR1(i,n) d[pos[i]]=next[i];
}
struct NODE
{
int L,R,det,Max;
void add(int x)
{
det+=x;
Max+=x;
}
};
NODE a[N<<2];
void pushUp(int t)
{
if(a[t].L==a[t].R) return;
a[t].Max=max(a[t*2].Max,a[t*2+1].Max);
}
void pushDown(int t)
{
if(a[t].L==a[t].R) return;
if(a[t].det)
{
a[t*2].add(a[t].det);
a[t*2+1].add(a[t].det);
a[t].det=0;
}
}
void build(int t,int L,int R)
{
a[t].det=0;
a[t].L=L;
a[t].R=R;
if(L==R)
{
a[t].Max=d[L];
return;
}
int M=(L+R)>>1;
build(t*2,L,M);
build(t*2+1,M+1,R);
pushUp(t);
}
void update(int t,int L,int R,int x)
{
if(L==a[t].L&&R==a[t].R)
{
a[t].add(x);
return;
}
pushDown(t);
int M=(a[t].L+a[t].R)>>1;
if(R<=M) update(t*2,L,R,x);
else if(L>M) update(t*2+1,L,R,x);
else update(t*2,L,M,x),update(t*2+1,M+1,R,x);
pushUp(t);
}
int query(int t,int L,int R)
{
if(a[t].L==L&&a[t].R==R) return a[t].Max;
pushDown(t);
int M=(a[t].L+a[t].R)>>1;
if(R<=M) return query(t*2,L,R);
if(L>M) return query(t*2+1,L,R);
return max(query(t*2,L,M),query(t*2+1,M+1,R));
}
int main()
{
init();
build(1,1,n);
int i,x,y;
char c;
FOR1(i,m)
{
if(Q[i].op[0]=='U')
{
x=get(Q[i].x);
y=get(Q[i].v);
if(x>y) swap(x,y);
f[y]=x;
end[x]=end[y];
}
else if(Q[i].op[0]=='A')
{
c=Q[i].op[1];
if(c=='1') update(1,pos[Q[i].x],pos[Q[i].x],Q[i].v);
else if(c=='2')
{
x=get(Q[i].x);
update(1,pos[x],end[x],Q[i].v);
}
else update(1,1,n,Q[i].x);
}
else
{
c=Q[i].op[1];
if(c=='1') PR(query(1,pos[Q[i].x],pos[Q[i].x]));
else if(c=='2')
{
x=get(Q[i].x);
PR(query(1,pos[x],end[x]));
}
else PR(query(1,1,n));
}
}
}