1180: [CROATIAN2009]OTOCI
Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 961 Solved: 594[][][]Description
给出n个结点以及每个点初始时对应的权值wi。起始时点与点之间没有连边。有3类操作: 1、bridge A B:询问结点A与结点B是否连通。如果是则输出“no”。否则输出“yes”,并且在结点A和结点B之间连一条无向边。 2、penguins A X:将结点A对应的权值wA修改为X。 3、excursion A B:如果结点A和结点B不连通,则输出“impossible”。否则输出结点A到结点B的路径上的点对应的权值的和。给出q个操作,要求在线处理所有操作。数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。
Input
第一行包含一个整数n(1<=n<=30000),表示节点的数目。第二行包含n个整数,第i个整数表示第i个节点初始时对应的权值。第三行包含一个整数q(1<=n<=300000),表示操作的数目。以下q行,每行包含一个操作,操作的类别见题目描述。任意时刻每个节点对应的权值都是1到1000的整数。
Output
输出所有bridge操作和excursion操作对应的输出,每个一行。
单点修改,链查询.....
貌似我还没写过splay的单点修改,好像只要修改t[x].w就可以了
链查询就是M A s得到x到y的链的Splay然后t[y].sum行了
注意:单点修改后别忘splay一下,这时候Access无所谓
Access的时候一定要更新,因为重新设置了rc嘛!!!!
#include#include #include #include #include using namespace std;#define pa t[x].fa#define lc t[x].ch[0]#define rc t[x].ch[1]const int N=3e4+5;inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}struct node{ int ch[2],fa,rev; int sum,w;}t[N];inline void update(int x){t[x].sum=t[lc].sum+t[rc].sum+t[x].w;}inline int wh(int x){ return t[pa].ch[1]==x;}inline int isRoot(int x){ return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}inline void pushDown(int x){ if(t[x].rev){ t[lc].rev^=1; t[rc].rev^=1; swap(lc,rc); t[x].rev=0; }}inline void rotate(int x){ int f=t[x].fa,g=t[f].fa,c=wh(x); if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g; t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f; t[x].ch[c^1]=f;t[f].fa=x; update(f);update(x);}int st[N],top;inline void splay(int x){ top=0;st[++top]=x; for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa; for(int i=top;i>=1;i--) pushDown(st[i]); for(;!isRoot(x);rotate(x)) if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);}inline void Access(int x){ for(int y=0;x;y=x,x=pa){ splay(x); rc=y; update(x); }}inline void MakeRoot(int x){ Access(x); splay(x); t[x].rev^=1;}inline int FindRoot(int x){ Access(x); splay(x); while(lc) x=lc; return x;}inline void Link(int x,int y){ MakeRoot(x); t[x].fa=y; splay(x);}int n,Q,x,y;char s[N];int main(){ //freopen("in.txt","r",stdin); n=read(); for(int i=1;i<=n;i++) t[i].w=t[i].sum=read(); Q=read(); while(Q--){ scanf("%s",s);x=read();y=read(); if(s[0]=='b'){ if(FindRoot(x)==FindRoot(y)) puts("no"); else puts("yes"),Link(x,y); }else if(s[0]=='p'){ t[x].w=y; //Access(x); splay(x); }else{ if(FindRoot(x)!=FindRoot(y)) puts("impossible"); else{ MakeRoot(x);Access(y);splay(y); printf("%d\n",t[y].sum); } } }}