bzoj3626 [LNOI2014]LCA

又是差分,然后利用标记求和求某对点lca的dep

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

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

想打主席树,没有实现,

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

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define N 50050
  7 #define mod 201314
  8 using namespace std;
  9 int n,m;
 10 int e=1,head[N];
 11 struct edge{int v,next;}ed[N];
 12 void add(int u,int v){
 13     ed[e].v=v;
 14     ed[e].next=head[u];
 15     head[u]=e++;
 16 }
 17 struct data{int pos,x,id,val;}d[N*2];
 18 bool cmp(data a,data b){
 19     return a.pos<b.pos;
 20 }
 21 int dep[N],size[N],fa[N],son[N],top[N],tot,id[N];
 22 void dfs1(int x,int d){
 23     dep[x]=d;size[x]=1;
 24     for(int i=head[x];i;i=ed[i].next){
 25         int v=ed[i].v;
 26         if(v==fa[x])continue;
 27         fa[v]=x; dfs1(v,d+1);
 28         size[x]+=size[v];
 29         if(size[v]>size[son[x]])son[x]=v;
 30     }
 31 }
 32 void dfs2(int x,int t){
 33     top[x]=t;id[x]=++tot;
 34     if(son[x])dfs2(son[x],t);
 35     for(int i=head[x];i;i=ed[i].next){
 36         int v=ed[i].v;
 37         if(v==fa[x]||v==son[x])continue;
 38         dfs2(v,v);
 39     }
 40 }
 41 int sum[4*N],lazy[4*N];
 42 inline void pushup(int rt){
 43     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 44 }
 45 inline void pushdown(int rt,int l,int r){
 46     if(lazy[rt]){
 47         int mid=(l+r)>>1;
 48         sum[rt<<1]+=lazy[rt]*(mid-l+1);
 49         lazy[rt<<1]+=lazy[rt];
 50         sum[rt<<1|1]+=lazy[rt]*(r-mid);
 51         lazy[rt<<1|1]+=lazy[rt];
 52         lazy[rt]=0;
 53     }
 54 }
 55 void update(int rt,int l,int r,int x,int y){
 56     if(x<=l&&r<=y){
 57         sum[rt]+=(r-l+1);
 58         lazy[rt]++;
 59         return ;
 60     }
 61     pushdown(rt,l,r);
 62     int mid=(l+r)>>1;
 63     if(x<=mid)update(rt<<1,l,mid,x,y);
 64     if(y>mid)update(rt<<1|1,mid+1,r,x,y);
 65     pushup(rt);
 66 }
 67 int query(int rt,int l,int r,int x,int y){
 68     if(x<=l&&r<=y)return sum[rt];
 69     pushdown(rt,l,r);
 70     int mid=(l+r)>>1,ans=0;
 71     if(x<=mid)ans+=query(rt<<1,l,mid,x,y);
 72     if(y>mid)ans+=query(rt<<1|1,mid+1,r,x,y);
 73     return ans;
 74 }
 75 void UPDATE(int x){
 76     while(x){
 77         update(1,1,n,id[top[x]],id[x]);
 78         x=fa[top[x]];
 79     }
 80 }
 81 int QUERY(int x){
 82     int ans=0;
 83     while(x){
 84         ans+=query(1,1,n,id[top[x]],id[x]);
 85         x=fa[top[x]];
 86     }
 87     return ans;
 88 }
 89 int ans[N];
 90 int main(){
 91     scanf("%d%d",&n,&m);
 92     for(int i=2,x;i<=n;i++){scanf("%d",&x);add(x+1,i);}
 93     dfs1(1,1);
 94     dfs2(1,1);
 95     for(int i=1,l,r,p;i<=m;i++){
 96         scanf("%d%d%d",&l,&r,&p);l++;r++;p++;
 97         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;
 98         d[i*2].pos=r;d[i*2].x=p;d[i*2].id=i;d[i*2].val=1;
 99     }
100     sort(d+1,d+2*m+1,cmp);
101     for(int i=1,j=1;i<=n;i++){
102         UPDATE(i);
103         while(j<=2*m&&d[j].pos<i)j++;
104         while(j<=2*m&&d[j].pos==i){
105             ans[d[j].id]+=d[j].val*QUERY(d[j].x);
106             j++;
107         }
108         if(j>2*m)break;
109     }
110     for(int i=1;i<=m;i++)
111         printf("%d\n",ans[i]%mod);
112     return 0;
113 }
bzoj3626

 

posted @ 2017-11-06 14:08  Ren_Ivan  阅读(189)  评论(0编辑  收藏  举报