您的位置:首页 > 其它

bzoj3626 [LNOI2014]LCA

2017-11-06 14:08 369 查看
又是差分,然后利用标记求和求某对点lca的dep

比如求a,b lca的dep,则把根到a的所有点标记,再在根到b的路径上求和,

于是就可以树剖了。前缀和差分一下就好了。

想打主席树,没有实现,

在线主席树具体可见[Troywar]

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 50050
#define mod 201314
using namespace std;
int n,m;
int e=1,head
;
struct edge{int v,next;}ed
;
void add(int u,int v){
ed[e].v=v;
ed[e].next=head[u];
head[u]=e++;
}
struct data{int pos,x,id,val;}d[N*2];
bool cmp(data a,data b){
return a.pos<b.pos;
}
int dep
,size
,fa
,son
,top
,tot,id
;
void dfs1(int x,int d){
dep[x]=d;size[x]=1;
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(v==fa[x])continue;
fa[v]=x; dfs1(v,d+1);
size[x]+=size[v];
if(size[v]>size[son[x]])son[x]=v;
}
}
void dfs2(int x,int t){
top[x]=t;id[x]=++tot;
if(son[x])dfs2(son[x],t);
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
}
int sum[4*N],lazy[4*N];
inline void pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline void pushdown(int rt,int l,int r){
if(lazy[rt]){
int mid=(l+r)>>1;
sum[rt<<1]+=lazy[rt]*(mid-l+1);
lazy[rt<<1]+=lazy[rt];
sum[rt<<1|1]+=lazy[rt]*(r-mid);
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void update(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
sum[rt]+=(r-l+1);
lazy[rt]++;
return ;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if(x<=mid)update(rt<<1,l,mid,x,y);
if(y>mid)update(rt<<1|1,mid+1,r,x,y);
pushup(rt);
}
int query(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y)return sum[rt];
pushdown(rt,l,r);
int mid=(l+r)>>1,ans=0;
if(x<=mid)ans+=query(rt<<1,l,mid,x,y);
if(y>mid)ans+=query(rt<<1|1,mid+1,r,x,y);
return ans;
}
void UPDATE(int x){
while(x){
update(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
}
int QUERY(int x){
int ans=0;
while(x){
ans+=query(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
return ans;
}
int ans
;
int main(){
scanf("%d%d",&n,&m);
for(int i=2,x;i<=n;i++){scanf("%d",&x);add(x+1,i);}
dfs1(1,1);
dfs2(1,1);
for(int i=1,l,r,p;i<=m;i++){
scanf("%d%d%d",&l,&r,&p);l++;r++;p++;
d[i*2-1].pos=l-1;d[i*2-1].x=p;d[i*2-1].id=i;d[i*2-1].val=-1;
d[i*2].pos=r;d[i*2].x=p;d[i*2].id=i;d[i*2].val=1;
}
sort(d+1,d+2*m+1,cmp);
for(int i=1,j=1;i<=n;i++){
UPDATE(i);
while(j<=2*m&&d[j].pos<i)j++;
while(j<=2*m&&d[j].pos==i){
ans[d[j].id]+=d[j].val*QUERY(d[j].x);
j++;
}
if(j>2*m)break;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]%mod);
return 0;
}


bzoj3626
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: