树链剖分+树状数组 模板题
#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;
}