BZOJ 3626 LCA(离线+树链剖分+差分)

 

显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1, r] − [1, l − 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n − 1 依次插入点 i,即将 i 到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT 均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log n),均可以完成任务。至此,题目已经被我们完美解决。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<vector>
  7 using namespace std;
  8 const long long N=51100;
  9 const long long mod=201314;
 10 long long cnt,head[N];
 11 long long size[N],fa[N],dep[N],son[N];
 12 long long top[N],id[N],tot;
 13 long long n,m,lm[N],rm[N];
 14 struct que{
 15     long long l,r,z;
 16 }q[N];
 17 struct tree{
 18     long long l,r,sum,lazy;
 19 }tr[N*8];
 20 vector<long long> l[N],r[N];
 21 struct edge{
 22     long long to,nxt;
 23 }e[N*2];
 24 void add(long long u,long long v){
 25     cnt++;
 26     e[cnt].nxt=head[u];
 27     e[cnt].to=v;
 28     head[u]=cnt;
 29 }
 30 void dfs1(long long u,long long f,long long deep){
 31     size[u]=1;
 32     fa[u]=f;
 33     dep[u]=deep;
 34     long long maxson=-1;
 35     for(long long i=head[u];i;i=e[i].nxt){
 36         long long v=e[i].to;
 37         if(v==f)continue;
 38         dfs1(v,u,deep+1);
 39         size[u]+=size[v];
 40         if(size[v]>maxson){
 41             maxson=size[v];
 42             son[u]=v;
 43         }
 44     }
 45 }
 46 void dfs2(long long u,long long tp){
 47     top[u]=tp;
 48     id[u]=++tot;
 49     if(!son[u])return;
 50     dfs2(son[u],tp);
 51     for(long long i=head[u];i;i=e[i].nxt){
 52         long long v=e[i].to;
 53         if(v==fa[u]||v==son[u])continue;
 54         dfs2(v,v); 
 55     }
 56 }
 57 void build(long long l,long long r,long long now){
 58     tr[now].l=l;tr[now].r=r;
 59     if(l==r)return;
 60     long long mid=(l+r)>>1;
 61     build(l,mid,now*2);
 62     build(mid+1,r,now*2+1);
 63 }
 64 void update(long long now){
 65     tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
 66     tr[now].sum%=mod;
 67 }
 68 void pushdown(long long now){
 69     if(tr[now].lazy==0)return;
 70     tr[now*2].sum+=((tr[now*2].r-tr[now*2].l+1)*tr[now].lazy)%mod;
 71     tr[now*2].sum%=mod;
 72     tr[now*2+1].sum+=((tr[now*2+1].r-tr[now*2+1].l+1)*tr[now].lazy)%mod;
 73     tr[now*2+1].sum%=mod;
 74     tr[now*2].lazy+=tr[now].lazy;
 75     tr[now*2].lazy%=mod;
 76     tr[now*2+1].lazy+=tr[now].lazy;
 77     tr[now*2+1].lazy%=mod;
 78     tr[now].lazy=0;
 79 }
 80 void change(long long l,long long r,long long now){
 81     pushdown(now);
 82     if(tr[now].l==l&&tr[now].r==r){
 83         tr[now].sum+=(tr[now].r-tr[now].l+1)%mod;
 84         tr[now].sum%=mod;
 85         tr[now].lazy+=1;
 86         return;
 87     }
 88     long long mid=(tr[now].l+tr[now].r)>>1;
 89     if(l>mid)change(l,r,now*2+1);
 90     else if(r<=mid)change(l,r,now*2);
 91     else{
 92         change(l,mid,now*2);
 93         change(mid+1,r,now*2+1); 
 94     } 
 95     update(now);
 96 }
 97 long long getsum(long long l,long long r,long long now){
 98     pushdown(now);
 99     if(tr[now].l==l&&tr[now].r==r){
100         return tr[now].sum;
101     }
102     long long mid=(tr[now].l+tr[now].r)>>1;
103     if(l>mid)return getsum(l,r,now*2+1);
104     else if(r<=mid)return getsum(l,r,now*2);
105     else {
106         return (getsum(l,mid,now*2)+getsum(mid+1,r,now*2+1))%mod;
107     }
108 }
109 void changel(long long x,long long y){
110     while(top[x]!=top[y]){
111         if(dep[top[x]]<dep[top[y]])swap(x,y);
112         change(id[top[x]],id[x],1);
113         x=fa[top[x]];
114     }
115     if(dep[x]>dep[y])swap(x,y);
116     change(id[x],id[y],1);
117 }
118 long long getsuml(long long x,long long y){
119     long long ans=0;
120     while(top[x]!=top[y]){
121         if(dep[top[x]]<dep[top[y]])swap(x,y);
122         ans+=getsum(id[top[x]],id[x],1);
123         ans%=mod;
124         x=fa[top[x]];
125     }
126     if(dep[x]>dep[y])swap(x,y);
127     ans+=getsum(id[x],id[y],1);
128     ans%=mod;
129     return ans;
130 }
131 int main(){
132     scanf("%lld%lld",&n,&m);
133     for(long long i=2;i<=n;i++){
134         long long u;
135         scanf("%lld",&u);
136         add(u+1,i);add(i,u+1);
137     }
138     dfs1(1,0,1);
139     dfs2(1,1);
140     build(1,n,1);
141     for(long long i=1;i<=m;i++){
142         scanf("%lld%lld%lld",&q[i].l,&q[i].r,&q[i].z);
143         q[i].l++;q[i].r++;q[i].z++;
144         l[q[i].l-1].push_back(i);
145         r[q[i].r].push_back(i);
146     }
147     for(long long i=1;i<=n;i++){
148         changel(i,1);
149         for(long long j=0;j<l[i].size();j++){
150             lm[l[i][j]]=getsuml(q[l[i][j]].z,1);
151         }
152         for(long long j=0;j<r[i].size();j++){
153             rm[r[i][j]]=getsuml(q[r[i][j]].z,1);
154         }
155     }
156     for(long long i=1;i<=m;i++){
157         printf("%lld\n",(rm[i]-lm[i]+mod)%mod);
158     }
159     return 0;
160 }

 

posted @ 2018-08-09 22:34  Xu-daxia  阅读(169)  评论(0编辑  收藏  举报