• 【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]<<'
    ';
    }
    
  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145541.html
Copyright © 2020-2023  润新知