显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 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 }

转载于:https://www.cnblogs.com/Xu-daxia/p/9452283.html

BZOJ 3626 LCA(离线+树链剖分+差分)相关推荐

  1. [BZOJ3626] [LNOI2014] LCA 离线 树链剖分

    题面 考虑到询问的\(l..r,z\)具有可减性,考虑把询问差分掉,拆成\(r,z\)和\(l-1,z\). 显然这些LCA一定在\(z\)到根的路径上.下面的问题就是怎么统计. 考虑不是那么暴力的暴 ...

  2. 数据结构课程设计-神秘国度的爱情故事-LCA:tarjan+离线/树链剖分/暴力

    1.无脑暴力dfs:   O(n*m) 2.LCA/tarjan+离线处理: O(n+m) 3.LCA/树链剖分: O(nlogn+m)~O(nlogn+mlogn) 4.LCA/倍增思想(有空再补) ...

  3. jzoj3626-[LNOI2014]LCA【树链剖分,线段树】

    正题 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3626 题目大意 一棵树,每次给出(l,r,z)(l,r,z)(l,r,z)询问∑i ...

  4. CodeChef - DGCD——树链剖分+差分

    [题目描述] You're given a tree on N vertices. Each vertex has a positive integer written on it, number o ...

  5. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  6. BZOJ 4034 [HAOI2015]T2 树链剖分

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  7. bzoj3083 遥远的国度 bzoj3626 LCA (树链剖分)

    今早刷了两道树剖的题目,用时两小时十五分钟= = 树剖的题目代码量普遍120+ 其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久 3083:裸树剖+"换根" ...

  8. BZOJ 4034: [HAOI2015]T2 树链剖分

    4034: [HAOI2015]T2 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操 ...

  9. bzoj 4127: Abs(树链剖分+线段树)

    4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 667  Solved: 225 [Submit][Status][Discuss ...

最新文章

  1. IF、如果、Rudyard Kipling
  2. java静态链表_数据结构笔记:静态链表(C语言)
  3. 静态成员函数不能采用const修饰的原因
  4. django 解决cors问题
  5. Python 数据处理函数 round()、int()、floor()、ceil()的用法
  6. 科大星云诗社动态20210821
  7. 【论文解读】Confluence:物体检测中不依赖IoU的NMS替代算法论文解析
  8. 百度:病种类贴吧全面停止商业合作
  9. silverlight之ToolTipService
  10. javafx 和swing_集成JavaFX和Swing
  11. gulp基础使用方法记录
  12. 实例27:python
  13. Linux中设置tab4个空格,linux下vim中tab设置为4个空格例子
  14. cnpack多国语言控件帮助
  15. Centos 安装SVN
  16. web2.0创业时代将终结
  17. 自建企业邮箱如何选择服务器
  18. PVE下的黑群晖的其他后续设置
  19. 联想笔记本上Ubuntu无线网卡问题
  20. 惠普 hp3414 笔记本 电脑 驱动 drivers

热门文章

  1. ASP.NET状态管理之十三(总结)
  2. 通过模板页master page和主题theme来实现网站的风格切换
  3. 强化学习《基于策略 - PPO,TRPO,PPO2》
  4. 漫步微积分二十七——曲线下的面积 定积分 黎曼
  5. gensim实现Doc2Vec和Word2Vec
  6. Harris及Shi-Tomasi原理及源码【转载】
  7. Opencv--undistortPoints()和cvUndistortPoints()
  8. oracle导出客户机使用us7a,导出已复制的文件系统 - Oracle® ZFS Storage Appliance 管理指南,发行版 OS8.6.0...
  9. adc采集出来一段波形 如何求周期与频率_DMA+ADC快速采集直流无刷电机电流
  10. STM32 - 定时器的设定 - 基础- 07 - 6-step PWM generation - 6步长PWM的产生 - COM Event的解释