BZOJ3626 [LNOI2014]LCA

来源:互联网 发布:晨兴资本 知乎 编辑:程序博客网 时间:2024/05/22 05:26

链剖,由于询问是询问一段区间内的所以我们建主席树,造两颗主席树,一个维护点的个数,一个维护点的深度和,对于每个点x,往根走,每走一条轻边到达轻边的父亲结点f,就在主席树上给f的点个数+1,深度和+f的深度(默认刚开始是走了一条轻边到达点x的)

查询的时候每走一条轻边到达一条重链上的结点x,求出重链上x和x以下有多少个点,再减去从来那条轻边底下来的点的个数,剩下这些点和询问点的lca都是x,用点的个数*x的深度记入答案,对于重链上x以上的点,LCA就是那些点,求深度和加到答案里,然后走到重链顶端的轻边上边并更新从轻边带上来的点数(默认刚开始是走了一条轻边到达询问点)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<iomanip>#include<ctime>#include<vector>#include<stack>#include<set>#include<bitset>#include<map>#include<queue>using namespace std;#define MAXN 50010#define MAXM 10000010#define MOD 201314#define INF 1000000000#define eps 1e-8#define ll long long struct vec{    int to;    int fro;};vec mp[MAXN*2];int tai[MAXN],cnt;int siz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],dfn[MAXN],ndf[MAXN],tp[MAXN],lw[MAXN],tim;int n,m,q;int srt[MAXN],drt[MAXN];int v[MAXM],Son[MAXM][2];int tot;int now;inline void be(int x,int y){    mp[++cnt].to=y;    mp[cnt].fro=tai[x];    tai[x]=cnt;}inline void bde(int x,int y){    be(x,y);    be(y,x);}void dfs1(int x){    int i,y;    siz[x]=1;    dep[x]=dep[fa[x]]+1;    for(i=tai[x];i;i=mp[i].fro){        y=mp[i].to;        if(!siz[y]){            fa[y]=x;            dfs1(y);            siz[x]+=siz[y];            if(siz[y]>siz[son[x]]){                son[x]=y;            }        }    }}void dfs2(int x,int z){    int i,y;    tp[x]=z;    lw[z]=x;    dfn[x]=++tim;    ndf[tim]=x;    if(son[x]){        dfs2(son[x],z);        for(i=tai[x];i;i=mp[i].fro){            y=mp[i].to;            if(!dfn[y]){                dfs2(y,y);            }        }    }}void change(int &x,int xx,int y,int z,int p,int cv){    x=++tot;    v[x]=(v[xx]+cv)%MOD;    memcpy(Son[x],Son[xx],sizeof(Son[x]));    if(y==z){        return ;    }    int mid=y+z>>1;    if(p<=mid){        change(Son[x][0],Son[xx][0],y,mid,p,cv);    }else{        change(Son[x][1],Son[xx][1],mid+1,z,p,cv);    }}void tochange(int x){    while(x){        change(srt[now],srt[now],1,n,dfn[x],1);        change(drt[now],drt[now],1,n,dfn[x],dep[x]);        x=fa[tp[x]];    }}int ask(int x,int xx,int y,int z,int l,int r){    if(l>r||!l){        return 0;    }    if(y==l&&z==r){        return (v[xx]-v[x]+MOD)%MOD;    }    int mid=y+z>>1;    if(r<=mid){        return ask(Son[x][0],Son[xx][0],y,mid,l,r);    }else if(l>mid){        return ask(Son[x][1],Son[xx][1],mid+1,z,l,r);    }else{        return (ask(Son[x][0],Son[xx][0],y,mid,l,mid)+ask(Son[x][1],Son[xx][1],mid+1,z,mid+1,r))%MOD;    }}int toask(int l,int r,int x){    int lu=0;    int re=0;    while(x){    (re+=(ll)ask(srt[l-1],srt[r],1,n,dfn[son[x]],dfn[lw[tp[x]]])*dep[x]%MOD)%=MOD;    (re+=(ll)(ask(srt[l-1],srt[r],1,n,dfn[x],dfn[x])-lu)*dep[x]%MOD)%=MOD;        (re+=ask(drt[l-1],drt[r],1,n,dfn[tp[x]],dfn[fa[x]]))%=MOD;        lu=ask(srt[l-1],srt[r],1,n,dfn[tp[x]],dfn[lw[tp[x]]]);        x=fa[tp[x]];        }    return re;}int main(){    int i,x,y,l,r;    scanf("%d%d",&n,&m);    for(i=2;i<=n;i++){        scanf("%d",&x);        x++;        bde(x,i);    }    dfs1(1);    dfs2(1,1);    for(now=1;now<=n;now++){    srt[now]=srt[now-1];    drt[now]=drt[now-1];    tochange(now);    }    while(m--){        scanf("%d%d%d",&l,&r,&x);        l++;        r++;        x++;        printf("%d\n",toask(l,r,x));    }    return 0;} /*7 1000 0 1 1 2 2 */


0 0
原创粉丝点击