题意:
多组数据。
n个兵营,m条道路,q个操作。
“I”:给C1和C2道路上的所有兵营都增加K个兵;
“D”:给C1和C2道路上的所有兵营都减少K个兵;
“Q”:查询第K个兵营的人。
真的好不容易,终于把这个程序给调过了。
题目<—
下面来讲述一下树链剖分;
至于dfs1和dfs2,就看这个神犇的博客<传送门>
下面由我来讲述一下用线段树来维护这道题.
change函数:
1.当他们不在同一重链上时,将不在同一重链的点移到自己重链的重儿子的父亲去,(当然一边提升,还要一边进行维护)在向上继续进行提升,直到他们在同一重链中。
2.当他们在同一重链中时,这就好办了,直接维护这两个点在重链位置中形成的区间(在对应的数据结构 ( 本题是线段树 ))。
/*
size[]数组,用来保存以x为根的子树节点个数
top[]数组,用来保存当前节点的所在链的顶端节点
son[]数组,用来保存重儿子
dep[]数组,用来保存当前节点的深度
fa[]数组,用来保存当前节点的父亲
tid[]数组,用来保存树中每个节点剖分后的新编号
rank[]数组,用来保存当前节点在线段树中的位置
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define ak(aa) memset(aa,0,sizeof(aa))
#define begin Begin
#define to To
#define next Next
#define rank Rank
#define size Size
#define lr node<<1
#define rr node<<1|1
using namespace std;
const int maxn=50010;
int n,m,q,sum;
int begin[maxn<<1],to[maxn<<1],next[maxn<<1],e;
int a[maxn];
int dep[maxn<<1],top[maxn<<1],rank[maxn<<1],son[maxn<<1],fa[maxn<<1],tid[maxn<<1],size[maxn<<1];
int lazy[maxn<<2],tree[maxn<<2];
struct tree_chain_partition{
void add(int x,int y){
to[++e]=y,next[e]=begin[x],begin[x]=e;
to[++e]=x,next[e]=begin[y],begin[y]=e;
}
void dfs1(int node,int father,int d){
dep[node]=d;
fa[node]=father;
size[node]=1;
for(int i=begin[node];i;i=next[i]){
int u=to[i];
if(u!=father){//无向图处理
dfs1(u,node,d+1);
size[node]+=size[u];
/*记录重儿子*/
if(son[node]==-1 || size[u]>size[son[node]]) son[node]=u;
}
}
}
void dfs2(int node,int t){
top[node]=t;
tid[node]=++sum;
rank[tid[node]]=node;
if(son[node]==-1) return ;
/*便利重链*/
dfs2(son[node],t);
for(int i=begin[node];i;i=next[i]){
int u=to[i];
/*轻链*/
if(u!=son[node] && u!=fa[node]){
dfs2(u,u);//开辟重链
}
}
}
void create_tree(int node,int l,int r){
lazy[node]=0;
if(l==r){
tree[node]=a[rank[l]];
return ;
}
int mid=(l+r)>>1;
create_tree(lr,l,mid);
create_tree(rr,mid+1,r);
tree[node]=tree[lr]+tree[rr];//在本题中毫无意义
}
void down(int node,int l,int r){
if(!lazy[node]) return ;
int mid=(l+r)>>1;
tree[lr]+=(mid-l+1)*lazy[node];
tree[rr]+=(r-mid)*lazy[node];
lazy[lr]+=lazy[node];
lazy[rr]+=lazy[node];
lazy[node]=0;
return ;
}
void update(int node,int l,int r,int be,int en,int ad){
if(be<=l && en>=r){
lazy[node]+=ad;
tree[node]+=(r-l+1)*ad;
return ;
}
down(node,l,r);
int mid=(l+r)>>1;
if(be<=mid) update(lr,l,mid,be,en,ad);
if(mid<en) update(rr,mid+1,r,be,en,ad);
tree[node]=tree[lr]+tree[rr];
return ;
}
int query(int node,int l,int r,int be,int en){
if(be<=l && en>=r){
return tree[node];
}
down(node,l,r);
int mid=(l+r)>>1,md=0;
if(be<=mid) md+=query(lr,l,mid,be,en);
if(mid<en) md+=query(rr,mid+1,r,be,en);
tree[node]=tree[lr]+tree[rr];
return md;
}
void change(int l,int r,int mdzz){
/*不同重链中*/
while(top[l]!=top[r]){
if(dep[top[l]]<dep[top[r]]) swap(l,r);//深的优先
update(1,1,n,tid[top[l]],tid[l],mdzz);//维护这一个区间
l=fa[top[l]];//提上去到另一条重链
}
/*同一重链中*/
if(dep[l]>dep[r]) swap(l,r);//保证序列
update(1,1,n,tid[l],tid[r],mdzz);
return ;
}
void init(){
ak(tree);
memset(begin,0,sizeof(begin));
memset(son,-1,sizeof(son));
e=0;sum=0;
}
void work(){
init();
For(i,1,n){
scanf("%d",&a[i]);
}
For(i,1,m){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
dfs1(1,1,0);
dfs2(1,1);
create_tree(1,1,n);
For(i,1,q){
char s[2];
scanf("%s",s);
if(s[0]=='Q'){
int x;
scanf("%d",&x);
printf("%d\n",query(1,1,n,tid[x],tid[x]));
}else{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(s[0]=='D') z=-z;
change(x,y,z);
}
}
return ;
}
}d;
int main(){
while(~scanf("%d%d%d",&n,&m,&q)) d.work();
return 0;
}