Luo Valley P4211 / LOJ2558 / BZOJ3626 [LNOI2014] LCA

First of all the $ dep [LCA (i, z)] $ certainly can not be determined directly, put it into consideration, found $ dep [LCA (i, z)] $ $ I $ is equivalent to the point on the path to the root black after, $ z $ path to the root of the number of black dots. After By extension, $ (l, r, z) $ corresponding to all answer is $ l \ le i \ le r $ a $ i $, $ I $ to the value of +1 point on the path to the root weight $ z $ and root weights.

Then consider how to maintain this thing. + Summing path plus the path tree may be a cross-sectional, right after interrogation point range ordering may be inserted only once, and then use the data structure durable then the difference, the $ (l, r, z) $ into $ (1, r, z) - (1, l- 1, z) $ can be done $ O (nlog ^ 2n) $ a.

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=201314;
const int N=50005;
char rB[1<<21],*rS,*rT,wB[1<<21];
int wp=-1;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;}
inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;}
inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;}
inline int rd(){
    char c=gc();
    while(c<48||c>57)c=gc();
    int x=c&15;
    for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
short buf[15];
inline void wt(int x){
    short l=-1;
    while(x>9){
        buf[++l]=x%10;
        x/=10;
    }
    pc(x|48);
    while(l>=0)pc(buf[l--]|48);
    pc('\n');
}
int G[N],to[N],nxt[N],cnt=0,f[N],sz[N],dep[N],son[N],top[N],id[N],dfsc=0,sum[N<<2],addv[N<<2],n,r[N<<1];
struct query{
    int r,z,s;
}a[N<<1];
inline bool cmp(int x,int y){return a[x].r<a[y].r;}
inline void add(int u,int v){
    to[++cnt]=v;nxt[cnt]=G[u];G[u]=cnt;
}
void dfs1(int u,int fa){
    int i,v,maxn=0;
    dep[u]=dep[f[u]=fa]+1;
    sz[u]=1;
    for(i=G[u];i;i=nxt[i]){
        dfs1(v=to[i],u);
        sz[u]+=sz[v];
        if(sz[v]>maxn)maxn=sz[son[u]=v];
    }
}
void dfs2(int u,int topf){
    int i,v;
    top[u]=topf;
    id[u]=++dfsc;
    if(!son[u])return;
    dfs2(son[u],topf);
    for(i=G[u];i;i=nxt[i])if((v=to[i])!=son[u])dfs2(v,v);
}
void add(int o,int L,int R,int x,int y){
    if(x<=L&&y>=R){++addv[o];if((sum[o]+=R-L+1)>=mod)sum[o]-=mod;}
    else{
        int lc=o<<1,rc=lc|1,M=L+R>>1;
        if(x<=M)add(lc,L,M,x,y);
        if(y>M)add(rc,M+1,R,x,y);
        sum[o]=(sum[lc]+sum[rc]+(ll)addv[o]*(R-L+1))%mod;
    }
}
int ask(int o,int L,int R,int x,int y){
    if(x<=L&&y>=R)return sum[o];
    int lc=o<<1,rc=lc|1,M=L+R>>1,ans=(ll)addv[o]*(min(y,R)-max(x,L)+1)%mod;
    if(x<=M&&(ans+=ask(lc,L,M,x,y))>=mod)ans-=mod;
    if(y>M&&(ans+=ask(rc,M+1,R,x,y))>=mod)ans-=mod;
    return ans;
}
inline void Add(int u){
    while(u){
        add(1,1,n,id[top[u]],id[u]);
        u=f[top[u]];
    }
}
inline int Ask(int u){
    int ans=0;
    while(u){
        if((ans+=ask(1,1,n,id[top[u]],id[u]))>=mod)ans-=mod;
        u=f[top[u]];
    }
    return ans;
}
int main(){
    int q,i,j=1;
    n=rd();q=rd();
    for(i=2;i<=n;++i)add(rd()+1,i);
    dfs1(1,0);
    dfs2(1,1);
    for(i=0;i<q;++i){a[i<<1|1].r=rd();a[i<<1].r=rd()+1;a[i<<1].z=a[i<<1|1].z=rd()+1;r[i<<1]=i<<1;r[i<<1|1]=i<<1|1;}
    sort(r,r+(q<<1),cmp);
    for(i=0;i<(q<<1);++i){
        for(;j<=a[r[i]].r;++j)Add(j);
        a[r[i]].s=Ask(a[r[i]].z);
    }
    for(i=0;i<q;++i)wt((a[i<<1].s-a[i<<1|1].s+mod)%mod);
    flush();
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/sunshine-chen/p/11288227.html