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
",query(1,n,1,rec[xx],rec[xx]+size[xx]-1));
    }
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532163.html