把树链剖分搞了一下,树链剖分就是把某树按重链和轻链映射到某一线性的数组上去,这样对于某条路径的查询和修改就变成了树状数组和线段树的事了。
这道题在HDU上要加个爆栈的,而且还要用c++,g++也会栈溢出
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=50100;
const long long inf=-1u>>1;
typedef long long ll;
struct Edge{
int v,next;
}edge[maxn*2];
int n,m,tot,pos;
int son[maxn],fa[maxn],head[maxn],num[maxn],deep[maxn],p[maxn],top[maxn];
int c[maxn],a[maxn];
char op[10];
void init() {
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
memset(c,0,sizeof(c));
tot=0;pos=1;
}
void addedge(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u,int pre,int d){//第一次dfs,计算结点数,深度,重儿子,父结点
deep[u]=d;
num[u]=1;
fa[u]=pre;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
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 dfs2(int u,int sp){//第二次dfs,计算链的根,每一结点对应树状数组的值
top[u]=sp;
p[u]=pos++;
//fp[p[u]]=u;
if(son[u]==-1) return;
dfs2(son[u],sp);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);//不是重儿子
}
}
void add(int i,int val){
while(i<=n){
c[i]+=val;
i+=i&(-i);
}
}
int sum(int i){
int s=0;
while(i>0){
s+=c[i];
i-=(-i)&i;
}
return s;
}
void change(int u,int v,int val) {
int f1=top[u],f2=top[v];
int tmp=0;
while(f1!=f2){
if(deep[f1]<deep[f2]){
swap(f1,f2);
swap(u,v);
}
add(p[f1],val);//把sum[i]表示为i点的值之后,对加上某段区间加上某值,对操作替换一下,就变成了区间首加上该值,并区间末+1减去该值
add(p[u]+1,-val);
u=fa[f1];
f1=top[u];
}
//printf("%d %d\n",p[u],p[v]+1);
if(deep[u]>deep[v]) swap(u,v);
add(p[u],val);
add(p[v]+1,-val);
//printf("dfsddf\n");
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int P;
while(scanf("%d%d%d",&n,&m,&P)==3){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
init();
int u,v;
int c1,c2,k,i;
for(i=1;i<=m;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
for(i=1;i<=n;i++){
add(p[i],a[i]);
printf("%d ",sum(p[i]));
add(p[i]+1,-a[i]);//在这里我们每次加上a[i]之后,还要减去a[i],以保证sum[i]==第i项的值
printf("%d\n",sum(p[i]+1));
}
while(P--) {
scanf("%s",op);
if(op[0]=='Q'){
scanf("%d",&u);
printf("%d\n",sum(p[u]));
}
else {
scanf("%d%d%d",&c1,&c2,&k);
if(op[0]=='D') k=-k;
change(c1,c2,k);
}
}
}
return 0;
}