题目大意:一些点,每个点有一个权值。有三种操作:连边,单点修改权值,求两点之间路径上点的权值和
题解:套路LCT~~~
我的收获:……
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int M=30005;
const int INF=1e9;
int n,m,y;
int a[M],sum[M];
int c[M][2],fa[M],st[M];
bool rev[M];
struct Link_Cut_Tree{
inline bool f(int x){return c[fa[x]][1]==x;}
inline bool isr(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
inline void pushup(int x){sum[x]=sum[c[x][0]]+sum[c[x][1]]+a[x];}
inline void pushdown(int x)
{
if(!rev[x]) return ;
int &l=c[x][0],&r=c[x][1];
rev[l]^=1;rev[r]^=1;swap(l,r);
rev[x]=0;
}
void rotate(int x)
{
int p=fa[x],g=fa[p],r;
bool k=f(x),m=f(p);r=c[x][k^1];
if(!isr(p)) c[g][m]=x;
fa[x]=g,c[x][k^1]=p;
fa[p]=x,c[p][k]=r;
if(r) fa[r]=p;
pushup(p),pushup(x);
}
void maintain(int x)
{
int top=0;st[++top]=x;
for(int i=x;!isr(i);i=fa[i]) st[++top]=fa[i];
for(int i=top;i>=1;i--) pushdown(st[i]);
}
void splay(int x)
{
maintain(x);
for(;!isr(x);rotate(x))
if(!isr(fa[x])) rotate(f(x)==f(fa[x])?fa[x]:x);
}
void access(int x){for(y=0;x;y=x,x=fa[x]) splay(x),c[x][1]=y,pushup(x);}
void rever(int x){access(x);splay(x);rev[x]^=1;}
void link(int x,int y){rever(y);fa[y]=x;}
void cut(int x,int y){rever(x);access(y);splay(y);fa[x]=c[y][0]=0;}
int fdrt(int x){access(x);splay(x);for(y=x;c[y][0];y=c[y][0]);return y;}
}T;
void work()
{
char opt[15];int u,v;
while(m--)
{
scanf("%s%d%d",opt,&u,&v);
if(opt[0]=='b'){
if(T.fdrt(u)==T.fdrt(v)) puts("no");
else T.link(u,v),puts("yes");
}
if(opt[0]=='p') a[u]=v,T.access(u),T.splay(u);
if(opt[0]=='e'){
if(T.fdrt(u)==T.fdrt(v)){
T.rever(u);
T.access(v),T.splay(v);
printf("%d\n",sum[v]);
}
else puts("impossible");
}
}
}
void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=a[i];
scanf("%d",&m);
}
int main()
{
init();
work();
return 0;
}