ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[LNOI2014]LCA

2021-05-09 02:04:20  阅读:217  来源: 互联网

标签:lf int top LNOI2014 ret rf LCA id


转:

[LNOI2014]LCA

Link

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
#include
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];="" node{="" s,tag;="" }t[n<<2];="" head[n],n,m,ans[n];;="" sz[n],top[n],son[n],dep[n],fa[n],in[n];="" inline="" void="" add(int="" id,int="" to){="" static="" cnt="0;" e[++cnt]="(E){head[id],to};" head[id]="cnt;" }="" dfs(int="" u){="" sz[u]="1;" for(int="" i="head[u];i;i=e[i].next){" 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("%dn",ans[i]);
}

标签:lf,int,top,LNOI2014,ret,rf,LCA,id
来源: https://www.cnblogs.com/wangtcc/p/14747037.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有