3626: [LNOI2014]LCA

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2074  Solved: 828
[Submit][Status][Discuss]

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。

Source

数据已加强 by saffah

[Submit][Status][Discuss]

树链剖分+线段树

显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 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 <bits/stdc++.h>
 2 const int siz = 50005;
 3 int n, m, hd[siz], to[siz], nt[siz], tot;
 4 long long ans[siz], sum[siz << 2], tag[siz << 2];
 5 int sz[siz], fa[siz], sn[siz], tp[siz], ps[siz], cnt;
 6 void dfs1(int u) {
 7     sz[u] = 1;
 8     for (int i = hd[u]; ~i; i = nt[i]) {
 9         fa[to[i]] = u; dfs1(to[i]); sz[u] += sz[to[i]];
10         if (sz[to[i]] > sz[sn[u]])sn[u] = to[i];
11     }
12 }
13 void dfs2(int u) {
14     if (sn[fa[u]] == u)tp[u] = tp[fa[u]];
15     else {
16         tp[u] = u;
17         for (int i = u; i; i = sn[i])
18             ps[i] = ++cnt;
19     }
20     for (int i = hd[u]; ~i; i = nt[i])dfs2(to[i]);
21 }
22 struct Q {
23     int x, y, z, id;
24     Q(void) {};
25     Q(int a, int b, int c, int d) :
26         x(a), y(b), z(c), id(d) {};
27 }q[siz << 1]; int qt;
28 bool operator < (const Q &a, const Q &b) {
29     return a.x < b.x;
30 }
31 void add(int t, int l, int r, long long k) {
32     tag[t] += k;
33     sum[t] += k * (r - l + 1);
34 }
35 void pushdown(int t, int l, int r) {
36     if (!tag[t])return;
37     int mid = (l + r) >> 1;
38     add(t << 1, l, mid, tag[t]);
39     add(t << 1 | 1, mid + 1, r, tag[t]);
40     tag[t] = 0LL;
41 }
42 void add(int t, int l, int r, int x, int y) {
43     if (l == x && y == r)add(t, l, r, 1);
44     else {
45         pushdown(t, l, r);
46         int mid = (l + r) >> 1;
47         if (y <= mid)add(t << 1, l, mid, x, y);
48         else if (x > mid)add(t << 1 | 1, mid + 1, r, x, y);
49         else add(t << 1, l, mid, x, mid), add(t << 1 | 1, mid + 1, r, mid + 1, y);
50         sum[t] = sum[t << 1] + sum[t << 1 | 1];
51     }
52 }
53 long long ask(int t, int l, int r, int x, int y) {
54     if (l == x && y == r)return sum[t];
55     pushdown(t, l, r);
56     int mid = (l + r) >> 1;
57     if (y <= mid)return ask(t << 1, l, mid, x, y);
58     if (x > mid)return ask(t << 1 | 1, mid + 1, r, x, y);
59     return ask(t << 1, l, mid, x, mid) + ask(t << 1 | 1, mid + 1, r, mid + 1, y);
60 }
61 void insert(int u) {
62     while (u) {
63         int v = tp[u];
64         add(1, 1, n, ps[v], ps[u]);
65         u = fa[v];
66     }
67 }
68 long long qry(int u) {
69     long long ret = 0;
70     while (u) {
71         int v = tp[u];
72         ret += ask(1, 1, n, ps[v], ps[u]);
73         u = fa[v];
74     }
75     return ret;
76 }
77 signed main(void) {
78 //    freopen("in", "r", stdin);
79     scanf("%d%d", &n, &m);
80     memset(hd, -1, sizeof(hd));
81     for (int i = 2, f; i <= n; ++i)
82         scanf("%d", &f), nt[tot] = hd[++f], to[tot] = i, hd[f] = tot++;
83     dfs1(1); dfs2(1);
84     for (int i = 1, x, y, z; i <= m; ++i) {
85         scanf("%d%d%d", &x, &y, &z); ++x, ++y, ++z;
86         q[qt++] = Q(x - 1, z, -1, i);
87         q[qt++] = Q(y, z, 1, i);
88     }
89     std::sort(q, q + qt);
90     for (int i = 0, j = 0; i <= n; ++i) {
91         insert(i);
92         for (; q[j].x == i; ++j)
93             ans[q[j].id] += q[j].z * qry(q[j].y);
94     }
95     for (int i = 1; i <= m; ++i)printf("%lld\n", ans[i] % 201314);
96 }

@Author: YouSiki

转载于:https://www.cnblogs.com/yousiki/p/6292224.html

BZOJ 3626: [LNOI2014]LCA相关推荐

  1. bzoj 3626: [LNOI2014]LCA(离线差分+树链剖分)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2885  Solved: 1133 [Submit][Sta ...

  2. 【BZOJ 3626】 [LNOI2014]LCA

    3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MB Submit: 735 Solved: 250 [Submit][Status] ...

  3. #HYSBZ3626[LNOI2014]#LCA(经典模型:树剖+线段树维护和)

    3626: [LNOI2014]LCA Time Limit: 10 Sec   Memory Limit: 128 MB Description 给出一个n个节点的有根树(编号为0到n-1,根节点为 ...

  4. P4211 [LNOI2014]LCA(离线 + 在线 做法)

    P4211 [LNOI2014]LCA 有一棵根节点为111树,有mmm次询问,每次给定l,r,zl, r, zl,r,z,输出∑i=lrdep[lca(i,z)]\sum\limits_{i = l ...

  5. 【做题记录】P4211 [LNOI2014]LCA

    P4211 [LNOI2014]LCA 题意 给出一个 \(n\) 个节点的有根树(编号为 \(0\) 到 \(n-1\),根节点为 \(0\)). 一个点的深度定义为这个节点到根的距离 \(+1\) ...

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

    显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案.观察到,深度其实就是上面有几个已 ...

  7. bzoj3626:[LNOI2014]LCA

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一 ...

  8. LNOI2014 LCA

    题目链接:戳我 区间求和可以分成前缀和差分,所以我们可以把每次询问的l,r差分成\([1,r]-[1,l-1]\) 对于每一组询问,我们把\([l,r]\)内的每个点到根的链上都+1,然后x和根的链上 ...

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

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

最新文章

  1. matlab二值化图像_小白啃骨头之图像识别
  2. MySQL存储过程---动态的表名
  3. SQL SERVER 2008 创建,删除,添加表的主键
  4. 代码实例--请求的转发:RequestDispatcher对象处理请求的两个方法--forward和include
  5. vsphere ha 虚拟机监控错误_学会这3招,分分钟迁移业务繁忙虚拟机!
  6. 日常使用计算机工具软件,计算机常用工具软件的使用.doc
  7. iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客
  8. 基于C++中常见内存错误的总结
  9. kettle中过滤记录中时间_Kettle中Step:Text file outpout功能
  10. 【人工智能】《Python深度学习》
  11. mysql query 原理_[转]MySQL的Query Cache原理
  12. 程序员,有什么资格去谈佛系?
  13. Android 常用语句
  14. DAY3 scp,rsync,chmod,chown,setfacl
  15. 网站apm测试软件,apm测试(手速apm在线测试)
  16. 翻译记忆软件-塔多思TRADO经典教程_4
  17. 类似宝塔linux面板,类似宝塔面板的软件有没有呢?
  18. 社会调查报告包括哪几个部分?
  19. python招聘-的python招聘
  20. Win10更新系统,VirtualBox与win10不兼容处理办法

热门文章

  1. ASP.NET MVC 3 Framework 学习笔记
  2. Javascript简明教程四 作用域
  3. Asp.net调用RAR压缩 解压文件
  4. c#_Func和Action委托简介
  5. dedecms 漏洞_代码审计之二次漏洞审计
  6. 八皇后算法python_Python学习二(生成器和八皇后算法)
  7. 自己建文件111 txt python_这可能是最详细的Python文件操作
  8. linux 磁盘扩容_当LINUX服务器磁盘空间不够时如何进行磁盘扩容?
  9. mysql 存储过程逻辑表达 and_MySQL - 存储过程 (二)- 逻辑判断语句
  10. spark并发读mysql_spark jdbc(mysql) 读取并发度优化