树链拆分+树阵
(进入坑....)
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2934 Accepted Submission(s): 806
For each case, The first line contains three integers N, M, P which means there will be N(1 ≤ N ≤ 50000) camps, M(M = N-1) edges and P(1 ≤ P ≤ 100000) operations. The number of camps starts from 1.
The next line contains N integers A1, A2, ...AN(0 ≤ Ai ≤ 1000), means at first in camp-i has Ai enemies.
The next M lines contains two integers u and v for each, denotes that there is an edge connects camp-u and camp-v.
The next P lines will start with a capital letter 'I', 'D' or 'Q' for each line.
'I', followed by three integers C1, C2 and K( 0≤K≤1000), which means for camp C1, C2 and all camps on the path from C1 to C2, increase K soldiers to these camps.
'D', followed by three integers C1, C2 and K( 0≤K≤1000), which means for camp C1, C2 and all camps on the path from C1 to C2, decrease K soldiers to these camps.
'Q', followed by one integer C, which is a query and means Aragorn wants to know the number of enemies in camp C at that time.
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=100500; struct Edge { int to,next; }edge[maxn]; int Adj[maxn],Size; void init_edge() { memset(Adj,-1,sizeof(Adj)); Size=0; } void add_edge(int u,int v) { edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++; } int fa[maxn],deep[maxn],num[maxn],son[maxn]; int top[maxn],p[maxn],rp[maxn],pos; void init() { init_edge(); memset(son,-1,sizeof(son)); pos=1; } void dfs1(int u,int pre,int d) { num[u]=1; fa[u]=pre; deep[u]=d; for(int i=Adj[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==pre) continue; dfs1(v,u,d+1); num[u]+=num[v]; if(son[u]==-1||num[son[u]]<num[v]) { son[u]=v; } } } void getPOS(int u,int to) { top[u]=to; p[u]=pos++; rp[p[u]]=u; if(son[u]!=-1) getPOS(son[u],to); for(int i=Adj[u];~i;i=edge[i].next) { int v=edge[i].to; if(v!=fa[u]&&v!=son[u]) getPOS(v,v); } } int tree[maxn]; int n,m,q; inline int lowbit(int x) { return x&(-x); } void ADD(int p,int v) { for(int i=p;i<=n;i+=lowbit(i)) tree[i]+=v; } int SUM(int p) { int ret=0; for(int i=p;i;i-=lowbit(i)) ret+=tree[i]; return ret; } void Change(int u,int v,int K) { int f1=top[u],f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } ADD(p[f1],K); ADD(p[u]+1,-K); u=fa[f1]; f1=top[u]; } if(deep[u]<deep[v]) swap(u,v); ADD(p[v],K); ADD(p[u]+1,-K); } int a[maxn]; int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init(); for(int i=1;i<=n;i++) scanf("%d",a+i); while(m--) { int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } dfs1(1,-1,0); getPOS(1,1); memset(tree,0,sizeof(tree)); for(int i=1;i<=n;i++) { ADD(p[i],a[i]); ADD(p[i]+1,-a[i]); } char ord; int a,b,c; while(q--) { scanf("%*c %c",&ord); if(ord=='Q') { scanf("%d",&a); printf("%d\n",SUM(p[a])); } else { scanf("%d%d%d",&a,&b,&c); if(ord=='D') c=-c; Change(a,b,c); } } } return 0; }