标签:
离线建树,树链剖分。
#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