zoukankan      html  css  js  c++  java
  • 【BZOJ3626】【LNOI2014】—Lca(树链剖分)

    传送门


    发现一次询问的答案就是把[l,r][l,r]所有点到根的路径+1+1
    zz到根的路径权值和

    离线差分就完了

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    const int N=50005;
    const int mod=201314;
    inline int add(int a,int b){
        return a+b>=mod?a+b-mod:a+b;
    }
    inline void Add(int &a,int b){
        a=add(a,b);
    }
    inline int dec(int a,int b){
        return a>=b?a-b:a-b+mod;
    }
    inline void Dec(int &a,int b){
        a=dec(a,b);
    }
    inline int mul(int a,int b){
        return 1ll*a*b>=mod?1ll*a*b%mod:a*b;
    }
    int n,m;
    namespace Seg{
        int tr[N<<2],tag[N<<2];
        #define lc (u<<1)
        #define rc ((u<<1)|1)
        #define mid ((l+r)>>1)
        inline void pushup(int u){
            tr[u]=add(tr[lc],tr[rc]);
        }
        inline void pushdown(int u,int l,int r){
            if(!tag[u])return;
            Add(tr[lc],mul(mid-l+1,tag[u]));
            Add(tr[rc],mul(r-mid,tag[u]));
            Add(tag[lc],tag[u]);
            Add(tag[rc],tag[u]);
            tag[u]=0;
        }
        void update(int u,int l,int r,int st,int des,int k){
            if(st<=l&&r<=des){Add(tag[u],k),Add(tr[u],mul(r-l+1,k));return;}
            pushdown(u,l,r);
            if(st<=mid)update(lc,l,mid,st,des,k);
            if(mid<des)update(rc,mid+1,r,st,des,k);
            pushup(u);
        }
        int query(int u,int l,int r,int st,int des){
            if(st<=l&&r<=des)return tr[u];
            pushdown(u,l,r);
            int res=0;
            if(st<=mid)Add(res,query(lc,l,mid,st,des));
            if(mid<des)Add(res,query(rc,mid+1,r,st,des));
            pushup(u);return res;
        }
    }
    using namespace Seg;
    namespace SLPF{
        int idx[N],in[N],siz[N],son[N],fa[N],top[N],dep[N],tot;
        int adj[N],nxt[N<<1],to[N<<1],cnt;
        void addedge(int u,int v){
            nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
        }
        void dfs1(int u){
            siz[u]=1;
            for(int e=adj[u];e;e=nxt[e]){
                int v=to[e];
                if(v==fa[u])continue;
                dep[v]=dep[u]+1,fa[v]=u;
                dfs1(v),siz[u]+=siz[v];
                if(siz[v]>siz[son[u]])son[u]=v;
            }
        }
        void dfs2(int u,int tp){
            top[u]=tp,in[u]=++tot,idx[tot]=u;
            if(son[u])dfs2(son[u],tp);
            for(int e=adj[u];e;e=nxt[e]){
                int v=to[e];
                if(v==fa[u]||v==son[u])continue;
                dfs2(v,v);
            }
        }
        inline int querypath(int u,int v){
            int res=0;
            while(top[u]!=top[v]){
                if(dep[top[u]]<dep[top[v]])swap(u,v);
                Add(res,query(1,1,n,in[top[u]],in[u]));
                u=fa[top[u]];
            }
            if(dep[u]<dep[v])swap(u,v);
            Add(res,query(1,1,n,in[v],in[u]));
            return res;
        }
        inline void updatepath(int u,int v){
            while(top[u]!=top[v]){
                if(dep[top[u]]<dep[top[v]])swap(u,v);
                update(1,1,n,in[top[u]],in[u],1);
                u=fa[top[u]];
            }
            if(dep[u]<dep[v])swap(u,v);
            update(1,1,n,in[v],in[u],1);
        }
    }
    using namespace SLPF;
    struct qry{
        int p,kd,id;
    };
    vector<qry> q[N];
    int ans[N],num;
    int main(){
        n=read(),m=read();
        for(int i=2;i<=n;i++){
            int u=read()+1;
            addedge(u,i),addedge(i,u);
        }
        dfs1(1),dfs2(1,1);
        for(int i=1;i<=m;i++){
            int l=read()+1,r=read()+1,p=read()+1;
            q[l-1].pb((qry){p,-1,i});
            q[r].pb((qry){p,1,i});
        }
        for(int i=1;i<=n;i++){
            updatepath(1,i);
            for(int j=0;j<q[i].size();j++){
                qry now=q[i][j];
                if(now.kd==-1)Dec(ans[now.id],querypath(1,now.p));
                else Add(ans[now.id],querypath(1,now.p));
            }
        }
        for(int i=1;i<=m;i++)cout<<ans[i]<<'
    ';
    }
    
  • 相关阅读:
    [原] KVM 虚拟化原理探究(6)— 块设备IO虚拟化
    [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化
    [原] KVM 虚拟化原理探究(4)— 内存虚拟化
    [原] KVM 虚拟化原理探究(3)— CPU 虚拟化
    [原] KVM 虚拟化原理探究(2)— QEMU启动过程
    [原] KVM虚拟机网络闪断分析
    [原] KVM 环境下MySQL性能对比
    [源]云计算技术堆栈系列——鸟瞰
    [原] 利用 OVS 建立 VxLAN 虚拟网络实验
    [原] Cgroup CPU, Blkio 测试
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145541.html
Copyright © 2011-2022 走看看