标签:
离线建树,树链剖分。
#include<bits/stdc++.h>
#define N 100010
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define L l,M,P
#define R M+1,r,S
#define Z int l=1,int r=n,int k=1
using namespace std;
int n,m;
struct edge{
edge* s;
int v;
}e[N],*back=e,*h[N];
void add(int u,int v){
h[u]=&(*back++=(edge){h[u],v});
h[v]=&(*back++=(edge){h[v],u});
}
typedef int ds[N];
ds d,a,z,dp,num,p,size,son,top;
void dfs1(int u){
dp[u]=dp[p[u]]+1;
size[u]=1;
int s=0;
for(edge* i=h[u];i;i=i->s)
if(i->v!=p[u]){
p[i->v]=u;
dfs1(i->v);
size[u]+=size[i->v];
if(s<size[i->v])
s=size[son[u]=i->v];
}
}
void dfs2(int u){
static int cnt;
d[num[u]=++cnt]=z[u];
if(size[u]!=1){
top[son[u]]=top[u];
dfs2(son[u]);
}
for(edge* i=h[u];i;i=i->s)
if(i->v!=p[u]&&i->v!=son[u])
dfs2(top[i->v]=i->v);
}
void build(Z){
if(l==r)
a[k]=d[l];
else{
build(L);
build(R);
a[k]=a[P]+a[S];
}
}
void A(int s,int t,Z){
if(l==r)
a[k]=s;
else{
if(t<=M)
A(s,t,L);
else
A(s,t,R);
a[k]=a[P]+a[S];
}
}
int Q(int s,int t,Z){
return s==l&&t==r?a[k]
:t<=M?Q(s,t,L)
:s>M?Q(s,t,R)
:Q(s,M,L)+Q(M+1,t,R);
}
int query(int s,int t){
int v=0;
while(top[s]!=top[t]){
if(dp[top[s]]<dp[top[t]])
swap(s,t);
v+=Q(num[top[s]],num[s]);
s=p[top[s]];
}
if(dp[s]<dp[t])
swap(s,t);
return v+Q(num[t],num[s]);
}
ds t,x,y;
char s[N][16];
bool st[N];
int find(int i){
return t[i]==i?i:t[i]=find(t[i]);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",z+i);
for(int i=1;i<=n;++i)
t[i]=i;
scanf("%d",&m);
for(int i=0;i!=m;++i){
scanf("%s%d%d",s[i],x+i,y+i);
if(*s[i]!=‘p‘)
st[i]=find(x[i])!=find(y[i]);
if(*s[i]==‘b‘&&st[i]){
add(x[i],y[i]);
t[find(x[i])]=find(y[i]);
}
}
for(int i=1;i<=n;++i)
if(!size[i]){
dfs1(i);
dfs2(top[i]=i);
}
build();
for(int i=0;i!=m;++i)
if(*s[i]==‘b‘)
puts(st[i]?"yes":"no");
else if(*s[i]==‘p‘)
A(y[i],num[x[i]]);
else if(st[i])
puts("impossible");
else
printf("%d\n",query(x[i],y[i]));
}
标签:
原文地址:http://www.cnblogs.com/f321dd/p/5496042.html