zoukankan      html  css  js  c++  java
  • [LNOI2014]LCA

    Description

    (q) 次询问,每次给定 (l,r,z) ,求

    [sum_{i=l}^r dep[Lca(i,z)] ]

    Solution

    如果不转换一下的话,应该是相当不好求。可以这样想,求两点 u 和 v 的 lca 的深度,其实就是求 u 和 v 到根的路径的交的大小。那么可以对其中一个点,修改其到根节点路径上的值,都加一。然后再查询另一个点到根节点路径上权值和。可以考虑树剖。

    类比这个思路,我们可以修改 l 到 r 的值,然后询问 z;也可以修改 z 然后询问 l 到 r。但是后者显然不能进一步优化。而前者的话,我们可以把它拆成两个前缀相减。那么后面的思路就很容易了,可以把所有 l 和 r 的询问离线,然后碰到就修改。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define lid id<<1
    #define rid id<<1|1
    
    const int Mod=201314;
    const int N=1e5+7;
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct Que{
        int l,pos,op,u;
        bool operator <(const Que &X) const{return l<X.l;}
    }q[N];
    
    struct E{
        int next,to;
    }e[N];
    
    struct Node{
        int s,tag;
    }t[N<<2];
    
    int head[N],n,m,ans[N];;
    int sz[N],top[N],son[N],dep[N],fa[N],in[N];
    
    inline void add(int id,int to){
        static int cnt=0;
        e[++cnt]=(E){head[id],to};
        head[id]=cnt;
    }
    
    void dfs(int u){
        sz[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            fa[v]=u,dep[v]=dep[u]+1;
            dfs(v),sz[u]+=sz[v];
            if(sz[u]>sz[son[u]]) son[u]=v;
        }
    }
    
    void Dfs(int u,int tp){
        static int tot=0;
        top[u]=tp,in[u]=++tot;
        if(!son[u]) return ;
        Dfs(son[u],tp);
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v!=son[u]) Dfs(v,v);
        }
    }
    
    inline void update(int id){t[id].s=t[lid].s+t[rid].s;}
    
    inline void push(int id,int val,int v){
        t[id].s=(t[id].s+val*v%Mod)%Mod;
        t[id].tag=(t[id].tag+val)%Mod;
    }
    
    void pushdown(int id,int lf,int rf){
        int mid=(lf+rf)>>1;
        push(lid,t[id].tag,mid-lf+1);
        push(rid,t[id].tag,rf-mid);
        t[id].tag=0;
    }
    
    int L,R;
    void modify(int id=1,int lf=1,int rf=n){
        if(L<=lf&&rf<=R){push(id,1,rf-lf+1);return ;}
        int mid=(lf+rf)>>1;
        if(t[id].tag) pushdown(id,lf,rf);
        if(L<=mid) modify(lid,lf,mid);
        if(R>mid) modify(rid,mid+1,rf);
        update(id);
    }
    
    int query(int id=1,int lf=1,int rf=n){
        if(L<=lf&&rf<=R) return t[id].s;
        int mid=(lf+rf)>>1,ret=0;
        if(t[id].tag) pushdown(id,lf,rf);
        if(L<=mid) ret=(ret+query(lid,lf,mid))%Mod;
        if(R>mid) ret=(ret+query(rid,mid+1,rf))%Mod;
        return ret;
    }
    
    void Modify(int u){
        while(top[u]!=top[1]){
            L=in[top[u]],R=in[u];
            modify(),u=fa[top[u]];
        }
        L=1,R=in[u],modify();
    }
    
    int Query(int u){
        int ret=0;
        while(top[u]!=top[1]){
            L=in[top[u]],R=in[u];
            ret=(ret+query())%Mod;
            u=fa[top[u]];
        }
        L=1,R=in[u];
        return (ret+query())%Mod;
    }
    
    int main(){
        n=read(),m=read();
        for(int i=2;i<=n;i++) add(read()+1,i);
        for(int i=1;i<=m;i++){
            int l=read()+1,r=read()+1,u=read()+1;
            q[(i<<1)-1]=(Que){r,i,1,u};
            q[i<<1]=(Que){l-1,i,-1,u};
        }
        sort(q+1,q+1+2*m);
        dep[1]=1,dfs(1),Dfs(1,1);
        for(int i=1,now=0;i<=2*m;i++){
            while(now!=q[i].l) Modify(++now);
            ans[q[i].pos]+=q[i].op*Query(q[i].u);
            ans[q[i].pos]=(ans[q[i].pos]%Mod+Mod)%Mod;
        }
        for(int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    LeetCode-198-打家劫舍
    LeetCode-279-完全平方数
    LeetCode-91-解码方法
    Redis RDB 分析工具 rdbtools 说明(转载)
    ftp软件下载,ftp软件到底在哪里下载
    element-ui组件库二次开发——打包、上传npm
    ftp客户端工具,这6款好用的ftp客户端工具,站长们必不可少的常用工具!
    不会用Java Future,我怀疑你泡茶没我快, 又是超长图文!!(转载)
    ftp管理软件,ftp管理软件怎么使用
    Android连载22-自定义广播之标准广播发送(转载)
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14663546.html
Copyright © 2011-2022 走看看