zoukankan      html  css  js  c++  java
  • BZOJ_3626_[LNOI2014]LCA_离线+树剖

    BZOJ_3626_[LNOI2014]LCA_离线+树剖

    题意:

    给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求$sumlimits_{lle ile r}dep(LCA(i,z))$。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    分析:

    求$sumlimits_{lle ile r}dep(LCA(i,z))$相当于把[l,r]区间内所有点依次插入。

    每次把点到1路径上所有点+1,可以发现z到1路径上的点权和即为所求。

    并且该操作具有区间可减性。那么我们把所有询问拆成[0~l-1],[0~r]两部分。

    排个序离线计算。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100050
    #define LL long long
    #define ls p<<1
    #define rs p<<1|1
    int head[N],to[N<<1],nxt[N<<1],cnt,n,m,r,mod=201314;
    int t[N<<2],lz[N<<2],tot;
    int siz[N],top[N],son[N],fa[N],dep[N],idx[N];
    LL now,ans[N];
    struct A{
        int pos,z,flg,id;
    }a[N];
    bool cmp(const A &x,const A &y){
        return x.pos<y.pos;
    }
    inline void add(int u,int v){
        to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;	
    }
    void dfs1(int x,int y){
        fa[x]=y;dep[x]=dep[y]+1;siz[x]=1;
        for(int i=head[x];i;i=nxt[i]){
            if(to[i]!=y){
                dfs1(to[i],x);
                siz[x]+=siz[to[i]];
                if(siz[to[i]]>siz[son[x]])son[x]=to[i];
            }
        }
    }
    void dfs2(int x,int t){
        top[x]=t;idx[x]=++tot;
        if(son[x])dfs2(son[x],t);
        for(int i=head[x];i;i=nxt[i]){
            if(to[i]!=fa[x]&&to[i]!=son[x])dfs2(to[i],to[i]);
        }
    }
    void pud(int l,int r,int p){
        if(!lz[p])return ;
        int mid=l+r>>1;
        lz[ls]=(lz[ls]+lz[p])%mod;
        lz[rs]=(lz[rs]+lz[p])%mod;
        t[ls]=(t[ls]+lz[p]*(mid-l+1))%mod;
        t[rs]=(t[rs]+lz[p]*(r-mid))%mod;
        lz[p]=0;
    }
    void up(int l,int r,int x,int y,int c,int p){
        if(x<=l&&r<=y){
            lz[p]=(lz[p]+c)%mod;
            t[p]=(t[p]+c*(r-l+1))%mod;return ;
        }
        pud(l,r,p);
        int mid=l+r>>1;
        if(x<=mid)up(l,mid,x,y,c,ls);
        if(y>mid)up(mid+1,r,x,y,c,rs);
        t[p]=(t[ls]+t[rs])%mod;
    }
    int query(int l,int r,int x,int y,int p){
        if(x<=l&&r<=y){
            return t[p];
        }
        pud(l,r,p);
        int mid=l+r>>1;
        int re=0;
        if(x<=mid)re=(re+query(l,mid,x,y,ls))%mod;
        if(y>mid)re=(re+query(mid+1,r,x,y,rs))%mod;
        return re;
    }
    void insert(int x){
        int y=1;
        while(top[x]!=top[y]){
            if(dep[top[x]]>dep[top[y]])swap(x,y);
            up(1,n,idx[top[y]],idx[y],1,1);
            y=fa[top[y]];
        }if(dep[x]<dep[y])swap(x,y);
        up(1,n,idx[y],idx[x],1,1);
    }
    LL ask(int x){
        LL re=0;
        int y=1;
        while(top[x]!=top[y]){
            if(dep[top[x]]>dep[top[y]])swap(x,y);
            re+=query(1,n,idx[top[y]],idx[y],1);
            re%=mod;
            y=fa[top[y]];
        }if(dep[x]<dep[y])swap(x,y);
        re+=query(1,n,idx[y],idx[x],1);
        re%=mod;
        return re;
    }
    int main(){
        scanf("%d%d",&n,&m);
        int x;
        for(int i=2;i<=n;i++){
            scanf("%d",&x);x++;
            add(x,i);add(i,x);
        }
        dfs1(1,0);
        dfs2(1,1);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a[i].pos,&a[i+m].pos,&a[i].z);
            a[i+m].pos++;a[i].z++;
            a[i+m].z=a[i].z;a[i].id=a[i+m].id=i;a[i+m].flg=1;
        }
        sort(a+1,a+m+m+1,cmp);
        int dir=0;
        for(int i=1;i<=m+m;i++){
            if(dir==a[i].pos){
                ans[a[i].id+a[i].flg*m]=ask(a[i].z);continue;
            }else{
                for(int j=dir+1;j<=a[i].pos;j++){
                    insert(j);
                }
                ans[a[i].id+a[i].flg*m]=ask(a[i].z);dir=a[i].pos;
            }
        }
        for(int i=1;i<=m;i++){
            printf("%lld
    ",(ans[i+m]-ans[i]+mod)%mod);
        }
    
    }
    /*
    
    5 2
    0
    0
    1
    1
    1 4 3
    1 4 2
    */
    
  • 相关阅读:
    Feli的生日礼物
    session cookie
    ArcGIS FLEXnet Licensing error:96,491错误解决
    CSS块元素与内联元素(转)
    铝伯世
    netsh修改IP及DNS

    JAVA代码查错(转)
    windows7查看占用端口的进程
    php 中文字符串截取子串
  • 原文地址:https://www.cnblogs.com/suika/p/8469725.html
Copyright © 2011-2022 走看看