[破碎的状态] Vijos 1986
看起来就是个树链剖分的题...
https://vijos.org/p/1986
所以直接树链剖分剖一下就好了..
所以写的好长啊..
代码:
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<time.h> #include<math.h> #include<memory> #include<vector> #include<bitset> #include<fstream> #include<stdio.h> #include<utility> #include<sstream> #include<string.h> #include<iostream> #include<stdlib.h> #include<algorithm> using namespace std; int a[100005]; struct edge { int y; edge * next; }; edge * li[100005]; edge * new_edge() { static edge a[200005]; static int top=0; return &a[top++]; } void inserts(int x,int y) { edge * t=new_edge(); t->y=y; t->next=li[x]; li[x]=t; } void insert_edge(int x,int y) { inserts(x,y); inserts(y,x); } edge * prefer[100005]; int dfn[100005]; int father[100005]; int size[100005]; int depth[100005]; int vis[100005]; void dfs1(int x) { size[x]=1; edge * t; int max_weight=0; for (t=li[x];t!=0;t=t->next) { if (t->y==father[x]) continue; father[t->y]=x; depth[t->y]=depth[x]+1; dfs1(t->y); size[x]+=size[t->y]; if (size[t->y]>max_weight) { max_weight=size[t->y]; prefer[x]=t; } } } int up[100005]; void dfs2(int x) { static int num=0; dfn[x]=num; vis[num]=x; num++; if (prefer[x]==0) return; up[prefer[x]->y]=up[x]; dfs2(prefer[x]->y); edge * t; for (t=li[x];t!=0;t=t->next) { if (t==prefer[x]) continue; if (t->y==father[x]) continue; up[t->y]=t->y; dfs2(t->y); } } int val[1<<18]; void build_tree(int num,int l,int r) { if (l==r-1) { val[num]=a[vis[l]]; return; } int mid=(l+r)/2; build_tree(num*2+1,l,mid); build_tree(num*2+2,mid,r); val[num]=val[num*2+1]+val[num*2+2]; } void change(int num,int l,int r,int k,int t) { if (l==r-1) { val[num]=t; return; } int mid=(l+r)/2; if (k<mid) change(num*2+1,l,mid,k,t); else change(num*2+2,mid,r,k,t); val[num]=val[num*2+1]+val[num*2+2]; } int query(int num,int l,int r,int l0,int r0) { if ((l0<=l)&&(r<=r0)) { return val[num]; } int mid=(l+r)/2; int sum=0; if (l0<mid) sum+=query(num*2+1,l,mid,l0,r0); if (mid<r0) sum+=query(num*2+2,mid,r,l0,r0); return sum; } int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int n; scanf("%d",&n); int i; for (i=0;i<n;i++) { scanf("%d",&a[i]); } for (i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); x--; y--; insert_edge(x,y); } depth[0]=0; father[0]=-1; dfs1(0); up[0]=0; dfs2(0); build_tree(0,0,n); int m; scanf("%d",&m); for (i=0;i<m;i++) { static char oper[5]; scanf("%s",oper); int x,y; scanf("%d%d",&x,&y); if (oper[0]=='C') { x--; change(0,0,n,dfn[x],y); } else { x--; y--; int sum=0; for (;;) { if (up[x]==up[y]) { if (depth[x]<depth[y]) swap(x,y); sum+=query(0,0,n,dfn[y],dfn[x]+1); break; } else { if (depth[up[x]]<depth[up[y]]) swap(x,y); sum+=query(0,0,n,dfn[up[x]],dfn[x]+1); x=father[up[x]]; } } printf("%d\n",sum); } } return 0; }