5
10
2016
0

[BZOJ3626] [LNOI2014]LCA

首先我们可以离线做

考虑每次把一条链上的权值全部加上1,然后询问z到根的值就是这个LCA的和

然后离线排序树剖一下直接做就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const int N=50005,Mod=201314;
 
int n,q,en,fa[N],h[N],cnt,dep[N],top[N],segn,siz[N],son[N],id[N];
 
struct Ask{
int z,ans1,ans2;
}Qu[N];
 
struct Option{
int id,p,flag;
friend bool operator<(Option A,Option B){return A.p<B.p;}
}Opt[2*N];
 
struct Edge{
int b,next;
}e[N];
 
void AddEdge(int sa,int sb){
e[++en].b=sb;
e[en].next=h[sa];
h[sa]=en;
}
 
struct SegTree{
int l,r,sum,tag;
}tree[4*N];
 
void Pushup(int rt){tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%Mod;}
 
void Pushdown(int rt){
if(tree[rt].tag){
    tree[rt<<1].tag=(tree[rt<<1].tag+tree[rt].tag)%Mod;
    tree[rt<<1|1].tag=(tree[rt<<1|1].tag+tree[rt].tag)%Mod;
    tree[rt<<1].sum=(tree[rt<<1].sum+tree[rt].tag*(tree[rt<<1].r-tree[rt<<1].l+1))%Mod;
    tree[rt<<1|1].sum=(tree[rt<<1|1].sum+tree[rt].tag*(tree[rt<<1|1].r-tree[rt<<1|1].l+1))%Mod;
    tree[rt].tag=0;
}
}
 
void Build(int rt,int l,int r){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){tree[rt].sum=0;tree[rt].tag=0;return;}
int mid=l+r>>1;
Build(rt<<1,l,mid);
Build(rt<<1|1,mid+1,r);
}
 
void Modify(int rt,int l,int r,int val){
if(l<=tree[rt].l && tree[rt].r<=r){
    tree[rt].tag=(tree[rt].tag+val)%Mod;
    tree[rt].sum=(tree[rt].sum+val*(tree[rt].r-tree[rt].l+1))%Mod;
    return;
}
Pushdown(rt);
int mid=tree[rt].l+tree[rt].r>>1;
if(l<=mid)Modify(rt<<1,l,r,val);
if(r>mid)Modify(rt<<1|1,l,r,val);
Pushup(rt);
}
 
int Query(int rt,int l,int r){
if(l<=tree[rt].l && tree[rt].r<=r)return tree[rt].sum;
int mid=tree[rt].l+tree[rt].r>>1,ans=0;
Pushdown(rt);
if(l<=mid)ans=(ans+Query(rt<<1,l,r))%Mod;
if(r>mid)ans=(ans+Query(rt<<1|1,l,r))%Mod;
return ans;
}
 
void dfs1(int u){
dep[u]=dep[fa[u]]+1;
siz[u]=1;
son[u]=0;
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(v==fa[u])continue;
    dfs1(v);
    siz[u]+=siz[v];
    if(siz[son[u]]<siz[v])son[u]=v;
}
}
 
void dfs2(int u,int ux){
top[u]=ux;
id[u]=++segn;
if(!son[u])return;
dfs2(son[u],ux);
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(son[u]==v || fa[u]==v)continue;
    dfs2(v,v);
}
}
 
void Update(int x){
while(top[x]!=top[1]){
    Modify(1,id[top[x]],id[x],1);
    x=fa[top[x]];
}
Modify(1,id[1],id[x],1);
}
 
int Solve(int x){
int ans=0;
while(top[x]!=top[1]){
    ans=(ans+Query(1,id[top[x]],id[x]))%Mod;
    x=fa[top[x]];
}
return (ans+Query(1,id[1],id[x]))%Mod;
}
 
int main(){
freopen("3626.in","r",stdin);
freopen("3626.out","w",stdout);
scanf("%d %d",&n,&q);
for(int i=2;i<=n;i++){scanf("%d",&fa[i]);fa[i]++;AddEdge(fa[i],i);}
dfs1(1);
dfs2(1,1);
Build(1,1,n);
for(int i=1;i<=q;i++){
    int x,y,z;
    scanf("%d %d %d",&x,&y,&z);
    x++;y++;z++;
    Qu[i].z=z;
    Opt[++cnt].id=i;
    Opt[cnt].p=x-1;
    Opt[cnt].flag=0;
    Opt[++cnt].id=i;
    Opt[cnt].p=y;
    Opt[cnt].flag=1;
}
sort(Opt+1,Opt+cnt+1);
int Now=1;
for(int i=1;i<=cnt;i++){
    while(Now<=Opt[i].p){Update(Now);Now++;}
    if(Opt[i].flag)Qu[Opt[i].id].ans2=Solve(Qu[Opt[i].id].z);
    else Qu[Opt[i].id].ans1=Solve(Qu[Opt[i].id].z);
}
for(int i=1;i<=q;i++){
    printf("%d\n",(Qu[i].ans2-Qu[i].ans1+Mod)%Mod);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 447

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com