[LNOI2014]LCA

Description

给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

Input

第一行2个整数n q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l r z。

Output

输出q行,每行表示一个询问的答案。每个答案对201314取模输出

Sample Input

5 2
0
0
1
1
1 4 3
1 4 2

Sample Output

8
5

HINT

共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

http://www.cnblogs.com/Y-E-T-I/p/8182129.html

根这道题很像

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 struct Node
  8 {
  9   int next,to;
 10 }edge[100001];
 11 int num,head[50001],size[50001],dep[50001],son[50001],top[50001],cnt,dfn[50001],pos;
 12 int ch[150*50001][2],root[50001],sum[150*50001],lazy[150*50001],n,fa[50001],pre[50001],ans;
 13 void add(int u,int v)
 14 {
 15   num++;
 16   edge[num].next=head[u];
 17   head[u]=num;
 18   edge[num].to=v;
 19 }
 20 void dfs1(int x,int pa)
 21 {int i;
 22   size[x]=1;
 23   for (i=head[x];i;i=edge[i].next)
 24     {
 25       int v=edge[i].to;
 26       if (v!=pa)
 27     {
 28       fa[v]=x;
 29       dep[v]=dep[x]+1;
 30       dfs1(v,x);
 31       size[x]+=size[v];
 32       if (size[son[x]]<size[v]) son[x]=v;
 33     }
 34     }
 35 }
 36 void dfs2(int x,int pa,int tp)
 37 {int i;
 38   top[x]=tp;
 39   dfn[x]=++cnt;
 40   if (son[x]) dfs2(son[x],x,tp);
 41   for (i=head[x];i;i=edge[i].next)
 42     {
 43       int v=edge[i].to;
 44       if (v!=pa&&v!=son[x])
 45     {
 46       dfs2(v,x,v);
 47     }
 48     }
 49 }
 50 void update(int &rt,int l,int r,int L,int R,int last)
 51 {
 52   if (rt<=last)
 53     {
 54       int Rt=rt;
 55       rt=++pos;
 56       ch[rt][0]=ch[Rt][0];ch[rt][1]=ch[Rt][1];
 57       sum[rt]=sum[Rt];
 58       lazy[rt]=lazy[Rt];
 59     }
 60   if (l>=L&&r<=R)
 61     {
 62       sum[rt]+=(r-l+1);
 63       sum[rt]%=201314;
 64       lazy[rt]+=1;
 65       return;
 66     }
 67   int mid=(l+r)/2;
 68   if (L<=mid) update(ch[rt][0],l,mid,L,R,last);
 69   if (R>mid) update(ch[rt][1],mid+1,r,L,R,last);
 70   sum[rt]=(sum[ch[rt][0]]+sum[ch[rt][1]]+(r-l+1)*lazy[rt])%201314;
 71 }
 72 int query(int rt,int l,int r,int L,int R)
 73 {
 74   if (!rt) return 0;
 75   if (l>=L&&r<=R)
 76     {
 77       return sum[rt];
 78     }
 79   int mid=(l+r)/2,s=0;
 80   if (L<=mid) s+=query(ch[rt][0],l,mid,L,R);
 81   if (R>mid) s+=query(ch[rt][1],mid+1,r,L,R);
 82   s%=201314;
 83   return s+(min(r,R)-max(l,L)+1)*lazy[rt];
 84 }
 85 void change(int &rt,int x,int last)
 86 {
 87   while (top[x])
 88     {
 89       update(rt,1,n,dfn[top[x]],dfn[x],last);
 90       x=fa[top[x]];
 91     }
 92 }
 93 int ask(int r,int x)
 94 {
 95   int s=0;
 96   while (top[x])
 97     {
 98       s+=query(root[r],1,n,dfn[top[x]],dfn[x]);
 99     s%=201314;
100     x=fa[top[x]];
101     }
102   return s;
103 }
104 int main()
105 {int q,i,v,l,r,z;
106   cin>>n>>q;
107   for (i=2;i<=n;i++)
108     {
109       scanf("%d",&v);v++;
110       add(v,i);
111     }
112   dep[1]=1;
113   dfs1(1,0);
114   dfs2(1,0,1);
115   for (i=1;i<=n;i++)
116     {
117       root[i]=root[i-1];
118       change(root[i],i,pre[i-1]);
119       pre[i]=pos;
120     }
121   for (i=1;i<=q;i++)
122     {
123       scanf("%d%d%d",&l,&r,&z);
124       l++;r++;z++;
125       ans=((ask(r,z)-ask(l-1,z)+201314)%201314)%201314;
126       printf("%d\n",ans);
127     }
128 }

 

posted @ 2018-01-08 21:58  Z-Y-Y-S  阅读(255)  评论(0编辑  收藏  举报