1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| #include<bits/stdc++.h> using namespace std; int n,m,op,x,y,a[150010]; namespace IO{ inline int read(){int res=0,f=1;char ch=getchar();while(!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch&15),ch=getchar();return res*f;} inline void write(int x){if(x<0) putchar('-'),x=-x;if(x<10) putchar(x+'0');else write(x/10),putchar(x%10+'0');} } namespace UFS{ int fa[150010][2]; inline int getfa(int x,int y){return fa[x][y]==x?x:fa[x][y]=getfa(fa[x][y],y);} inline void merge(int x,int y,int z){if(x=getfa(x,z),y=getfa(y,z),x!=y) fa[x][z]=y;} } namespace LCT{ struct node{int s,v,ch[2],fa,tag;}tr[150010]; int stk[150010],top; inline bool isroot(int x){return tr[UFS::getfa(tr[x].fa,1)].ch[0]!=x&&tr[UFS::getfa(tr[x].fa,1)].ch[1]!=x;} inline void pushup(int x){tr[x].s=tr[x].v+tr[tr[x].ch[0]].s+tr[tr[x].ch[1]].s;} inline void flip(int x){swap(tr[x].ch[0],tr[x].ch[1]);tr[x].tag^=1;} inline void pushdown(int x){ if(!tr[x].tag) return ; if(tr[x].ch[0]) flip(tr[x].ch[0]); if(tr[x].ch[1]) flip(tr[x].ch[1]); tr[x].tag=0; } inline void rotate(int x){ int y=UFS::getfa(tr[x].fa,1),z=UFS::getfa(tr[y].fa,1),k=tr[y].ch[1]==x,v=tr[x].ch[!k]; if(!isroot(y)) tr[z].ch[tr[z].ch[1]==y]=x; tr[x].ch[!k]=y,tr[y].ch[k]=v; if(v) tr[v].fa=y; tr[y].fa=x,tr[x].fa=z; pushup(y),pushup(x); } inline void splay(int x){ int y=x,z;top=0;stk[++top]=y; while(!isroot(y)) stk[++top]=y=tr[y].fa; while(top) pushdown(stk[top--]); while(!isroot(x)){ y=UFS::getfa(tr[x].fa,1),z=UFS::getfa(tr[y].fa,1); if(!isroot(y)) rotate((tr[y].ch[0]==x)^(tr[z].ch[0]==y)?x:y); rotate(x); } pushup(x); } inline void access(int x){for(int y=0;x;x=UFS::getfa(tr[y=x].fa,1)) splay(x),tr[x].ch[1]=y,pushup(x);} inline void makeroot(int x){access(x),splay(x),flip(x);} inline int findroot(int x){access(x),splay(x);while(tr[x].ch[0]) pushdown(x),x=tr[x].ch[0];return x;} inline void split(int x,int y){makeroot(x),access(y),splay(y);} inline void link(int x,int y){makeroot(x);tr[x].fa=y;} inline void cut(int x,int y){split(x,y);if(findroot(y)==x&&tr[x].fa==y&&!tr[x].ch[1]) tr[x].fa=tr[y].ch[0]=0,pushup(y);} inline void reset(int x){tr[x].fa=tr[x].ch[0]=tr[x].ch[1]=0,pushup(x);} inline void change(int x,int y){int t=UFS::getfa(x,1);splay(t),tr[t].v-=a[x],a[x]=y,tr[t].v+=a[x],pushup(x);} } inline int dfs(int f,int x){ if(!x) return 0; UFS::fa[x][1]=f; return dfs(f,LCT::tr[x].ch[0])+dfs(f,LCT::tr[x].ch[1])+LCT::tr[x].v; } int main(){ n=IO::read(),m=IO::read(); for(int i=1;i<=n;i++) UFS::fa[i][0]=UFS::fa[i][1]=i,LCT::tr[i].s=LCT::tr[i].v=a[i]=IO::read(); for(int i=1;i<=m;i++){ op=IO::read(),x=IO::read(),y=IO::read(); if(op==1){ if(x=UFS::getfa(x,1),y=UFS::getfa(y,1),x==y) continue ; if(UFS::getfa(x,0)!=UFS::getfa(y,0)) LCT::link(x,y),UFS::merge(x,y,0); else LCT::split(x,y),LCT::tr[x].v=dfs(x,y),LCT::reset(x); }else if(op==2) LCT::change(x,y); else if(op==3){ if(UFS::getfa(x,0)!=UFS::getfa(y,0)){puts("-1");continue ;} x=UFS::getfa(x,1),y=UFS::getfa(y,1),LCT::split(x,y),IO::write(LCT::tr[y].s),putchar('\n'); } } }
|