显然是动态树裸题:O(mlogn)
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; int sumv[maxn],val[maxn],pre[maxn],fa[maxn],ch[maxn][2],flip[maxn]; void maintain(int x) {sumv[x]=sumv[ch[x][0]]+sumv[ch[x][1]]+val[x];} void pushdown(int x) { if(!flip[x]) return; flip[ch[x][0]]^=1;flip[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]);flip[x]=0; } void rotate(int x,int d) { pushdown(x);int y=pre[x],z=pre[y]; pre[ch[x][d]]=y;ch[y][d^1]=ch[x][d]; pre[x]=z;ch[z][ch[z][1]==y]=x; pre[y]=x;ch[x][d]=y;maintain(y); } void splay(int x) { int rt=x;while(pre[rt]) rt=pre[rt]; if(rt!=x) { fa[x]=fa[rt];fa[rt]=0; while(pre[x]) pushdown(pre[x]),rotate(x,ch[pre[x]][0]==x); maintain(x); } else pushdown(x); } void access(int x) { for(int y=0;x;x=fa[x]) { splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x; ch[x][1]=y;pre[y]=x;fa[y]=0; maintain(x);y=x; } } int findrt(int x) { access(x);splay(x); while(ch[x][0]) x=ch[x][0];return x; } void makeroot(int x) {access(x);splay(x);flip[x]^=1;} void link(int x,int y) {makeroot(x);fa[x]=y;} void query(int x,int y) {makeroot(x);access(y);splay(y);printf("%d\n",sumv[y]);} int main() { int n=read(); for(int i=1;i<=n;i++) val[i]=read(); int m=read(); while(m--) { char cmd=getchar();while(!isalpha(cmd)) cmd=getchar(); int x=read(),y=read(); if(cmd=='e') { if(findrt(x)==findrt(y)) query(x,y); else puts("impossible"); } else { if(findrt(x)==findrt(y)) puts("no"); else link(x,y),puts("yes"); } } return 0; }