zoukankan      html  css  js  c++  java
  • 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));
        }
    }

    这里写图片描述

  • 相关阅读:
    图匹配板子
    线性基
    Berlekamp-Massey algorithm
    组合/概率/形式幂级数/多项式/集合幂级数的题
    费用流 Dijkstra 原始对偶方法(primal-dual method)
    UVA-12304
    二项式系数
    卡特兰数
    多项式模板
    工具
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532163.html
Copyright © 2011-2022 走看看