HDU-3966 Aragorn's Story
阿新 • • 發佈:2018-11-10
樹鏈剖分+樹狀陣列 模板題
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int N=50000+10; //樹狀陣列 int lowbit(int x) {return x&(-x);} int c[N]; int n; int sum(int i) { int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s; } void add(int i,int val) { while(i<=n) { c[i]+=val; i+=lowbit(i); } } // struct Edge { int to,nxt; }edge[N*2]; int first[N],tot; void addedge(int u,int v) { edge[tot].to=v; edge[tot].nxt=first[u]; first[u]=tot++; } int top[N]; //樹鏈起點 int fa[N]; //父節點 int deep[N]; //深度 int num[N]; //子樹節點個數 int p[N]; //編號 int fp[N]; int son[N]; //重兒子 int pos; void init() { tot=0; memset(first,-1,sizeof(first)); pos=1; //編號從1開始 memset(son,-1,sizeof(son)); } //樹鏈 void dfs1(int u,int pre,int d) { deep[u]=d; fa[u]=pre; num[u]=1; for(int i=first[u];i!=-1;i=edge[i].nxt) { int v=edge[i].to; if(v==pre) continue; dfs1(v,u,d+1); num[u]+=num[v]; if(son[u]==-1||num[v]>num[son[u]]) son[u]=v; } } void getpos(int u,int sp) { top[u]=sp; p[u]=pos++; fp[p[u]]=u; if(son[u]==-1) return; getpos(son[u],sp); for(int i=first[u];i!=-1;i=edge[i].nxt) { int v=edge[i].to; if(v!=son[u]&&v!=fa[u]) getpos(v,v); } } void change(int u,int v,int val) { int f1=top[u],f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } add(p[f1],val); //樹狀陣列改為區間更新,單點查詢,以這種方式操作sum(i)即是i點的值 add(p[u]+1,-val); //等價為p[f1]~p[u]加上val u=fa[f1]; f1=top[u]; } if(deep[u]>deep[v]) swap(u,v); add(p[u],val); add(p[v]+1,-val); } int a[N]; int main() { int m,P; int c1,c2,val; char s[5]; while(~scanf("%d%d%d",&n,&m,&P)) { init(); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<m;i++) { scanf("%d%d",&c1,&c2); addedge(c1,c2); addedge(c2,c1); } dfs1(1,0,0); getpos(1,1); memset(c,0,sizeof(c)); for(int i=0;i<n;i++) { add(p[i+1],a[i]); add(p[i+1]+1,-a[i]); } while(P--) { scanf("%s",s); if(s[0]=='I') { scanf("%d%d%d",&c1,&c2,&val); change(c1,c2,val); } else if(s[0]=='D') { scanf("%d%d%d",&c1,&c2,&val); change(c1,c2,-val); } else if(s[0]=='Q') { scanf("%d",&val); printf("%d\n",sum(p[val])); } } } return 0; }