[bzoj3626]LCA

询问可以理解为将所有l~r的节点到根的路径都打上+1标记,然后询问相当于查询z到根的路径中有多少+1标记,这个问题可以转化为前缀和离线处理,用树链剖分套线段树维护。

还有一种分块的做法,对于每一个节点预处理出其到每一个块的答案,对于每一个块,可以发现f[k]=f[fa]+sz[k],其中sz[k]表示k的子树在这个块内的节点数量,先预处理s在计算f即可,最后块内直接计算,块外暴力(不需要套数据结构,但常数较大,可能过不了)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 50005
 4 #define L (k<<1)
 5 #define R (L+1)
 6 #define mid (l+r>>1)
 7 struct ji{
 8     int id,x,y,z;
 9     bool operator < (const ji &a)const{
10         return x<a.x;
11     }
12 }q[N<<1];
13 struct ji2{
14     int nex,to;
15 }edge[N<<1];
16 int E,n,m,x,y,z,k,sz[N],fa[N],top[N],id[N],ans[N],ma[N],head[N],laz[N<<2],f[N<<2];
17 void add(int x,int y){
18     edge[E].nex=head[x];
19     edge[E].to=y;
20     head[x]=E++;
21 }
22 void dfs(int k){
23     sz[k]=1;
24     for(int i=head[k];i!=-1;i=edge[i].nex){
25         dfs(edge[i].to);
26         sz[k]+=sz[edge[i].to];
27         if (sz[edge[i].to]>sz[ma[k]])ma[k]=edge[i].to;
28     }
29 }
30 void dfs2(int k,int t){
31     id[k]=++x;
32     top[k]=t;
33     if (ma[k])dfs2(ma[k],t); 
34     for(int i=head[k];i!=-1;i=edge[i].nex)
35         if (edge[i].to!=ma[k])dfs2(edge[i].to,edge[i].to);
36 }
37 void up(int k,int p,int l,int r){
38     laz[k]+=p;
39     f[k]+=p*(r-l+1);
40 }
41 void down(int k,int l,int r){
42     up(L,laz[k],l,mid);
43     up(R,laz[k],mid+1,r);
44     laz[k]=0;
45 }
46 void update(int k,int l,int r,int x,int y){
47     if ((l>y)||(x>r))return;
48     if ((x<=l)&&(r<=y)){
49         up(k,1,l,r);
50         return;
51     }
52     update(L,l,mid,x,y);
53     update(R,mid+1,r,x,y);
54     f[k]=f[L]+f[R]+laz[k]*(r-l+1);
55 }
56 int query(int k,int l,int r,int x,int y){
57     if ((l>y)||(x>r))return 0;
58     if ((x<=l)&&(r<=y))return f[k];
59     down(k,l,r);
60     return query(L,l,mid,x,y)+query(R,mid+1,r,x,y);
61 }
62 int calc(int k){
63     int s=0;
64     for(;k;k=fa[top[k]])s+=query(1,1,n,id[top[k]],id[k]);
65     return s;
66 }
67 int main(){
68     scanf("%d%d",&n,&m);
69     memset(head,-1,sizeof(head));
70     for(int i=2;i<=n;i++){
71         scanf("%d",&x);
72         add(++x,i);
73         fa[i]=x;
74     }
75     dfs(1);
76     x=0;
77     dfs2(1,1);
78     for(int i=1;i<=m;i++){
79         scanf("%d%d%d",&x,&y,&z);
80         if (x)q[++k]=ji{i,x,z+1,-1};
81         q[++k]=ji{i,y+1,z+1,1};
82     }
83     sort(q+1,q+k+1);
84     for(int i=1,j=1;i<=n;i++){
85         for(int k=i;k;k=fa[top[k]])update(1,1,n,id[top[k]],id[k]);
86         for(;q[j].x==i;j++)ans[q[j].id]+=calc(q[j].y)*q[j].z;
87     }
88     for(int i=1;i<=m;i++)printf("%d\n",ans[i]%201314);
89 }
View Code

 

posted @ 2019-07-28 10:37  PYWBKTDA  阅读(86)  评论(0编辑  收藏  举报