BZOJ 2836 树链剖分+线段树
思路:
链剖+线段树裸题
重链的标号就是DFS序
所以查子树的时候每回就 query(change[x],change[x]+size[x]-1)
就好了
剩下的应该都会吧。。
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
#define N 100050
char op[19];
int n,m,xx,yy,ww,first[N],next[N],v[N],tot,tree[N*16],mark[N*16];
int fa[N],rec[N],cnt,deep[N],size[N],son[N],top[N],p[N];
void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void dfs(int x){
size[x]=1,son[x]=-1;
for(int i=first[x];~i;i=next[i]){
deep[v[i]]=deep[x]+1;
dfs(v[i]);
size[x]+=size[v[i]];
if(son[x]==-1||size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int tp){
top[x]=tp,rec[x]=++cnt;
if(~son[x])dfs2(son[x],tp);
for(int i=first[x];~i;i=next[i]){
if(v[i]!=son[x])dfs2(v[i],v[i]);
}
}
void push_down(int pos,int cover){
int lson=pos<<1,rson=pos<<1|1;
mark[lson]+=mark[pos],mark[rson]+=mark[pos];
tree[lson]+=(cover-cover/2)*mark[pos];
tree[rson]+=cover/2*mark[pos];
mark[pos]=0;
}
void insert(int l,int r,int pos,int L,int R,int wei){
if(l>=L&&r<=R){tree[pos]+=wei*(r-l+1),mark[pos]+=wei;return;}
if(mark[pos])push_down(pos,r-l+1);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)insert(mid+1,r,rson,L,R,wei);
else if(mid>=R)insert(l,mid,lson,L,R,wei);
else insert(l,mid,lson,L,R,wei),insert(mid+1,r,rson,L,R,wei);
tree[pos]=tree[lson]+tree[rson];
}
void Add(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]<deep[fy])swap(x,y),swap(fx,fy);
insert(1,n,1,rec[fx],rec[x],ww);
x=fa[fx],fx=top[x];
}
if(deep[x]>deep[y])swap(x,y);
insert(1,n,1,rec[x],rec[y],ww);
}
int query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return tree[pos];
if(mark[pos])push_down(pos,r-l+1);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)return query(mid+1,r,rson,L,R);
else if(mid>=R)return query(l,mid,lson,L,R);
else return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
}
signed main(){
memset(first,-1,sizeof(first));
scanf("%lld",&n);
for(int i=1;i<n;i++){
scanf("%lld%lld",&xx,&yy);
fa[yy]=xx,add(xx,yy);
}
dfs(0),dfs2(0,0);
scanf("%lld",&m);
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='A')scanf("%lld%lld%lld",&xx,&yy,&ww),Add(xx,yy);
else scanf("%lld",&xx),printf("%lld\n",query(1,n,1,rec[xx],rec[xx]+size[xx]-1));
}
}