P4211 [LNOI2014]LCA
P4211 [LNOI2014]LCA
分析:
首先一种比较有趣的转化是,将所有点到1的路径上都+1,然后z到1的路径上的和,就是所有答案的deep的和。
对于多次询问,要么考虑有把询问离线,省去每次询问的复杂度,多个一起处理,要么做到优化掉查询。
这里发现求deep和的过程不能在省了,于是可以差分询问,枚举右端点,然后查询所有1到这个点的和。
而第一步的操作可以树链剖分完成。(并且查询的是一个区间,这也保证了这样做可行)
复杂度$O(nlog^2n)$
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define pa pair<int,int>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = , mod = ;
struct Edge{ int to, nxt; } e[N << ];
int head[N], sum[N << ], tag[N << ], fa[N], siz[N], son[N], bel[N], xl[N], ans[N];
int En, Index, n;
vector< pa > Que[N]; inline void add_edge(int u,int v) {
++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En;
}
inline void pushdown(int rt,int len) {
sum[rt << ] += (len - (len / )) * tag[rt];
sum[rt << | ] += (len / ) * tag[rt];
tag[rt << ] += tag[rt];
tag[rt << | ] += tag[rt];
tag[rt] = ;
}
void update(int l,int r,int rt,int L,int R) {
if (L <= l && r <= R) {
tag[rt] ++; (sum[rt] += r - l + ) %= mod; return ;
}
if (tag[rt]) pushdown(rt, r - l + );
int mid = (l + r) >> ;
if (L <= mid) update(l, mid, rt << , L, R);
if (R > mid) update(mid + , r, rt << | , L, R);
sum[rt] = (sum[rt << ] + sum[rt << | ]) % mod;
}
int query(int l,int r,int rt,int L,int R) {
if (L <= l && r <= R) return sum[rt];
if (tag[rt]) pushdown(rt, r - l + );
int mid = (l + r) >> , res = ;
if (L <= mid) res = (res + query(l, mid, rt << , L, R)) % mod;
if (R > mid) res = (res + query(mid + , r, rt << | , L, R)) % mod;
return res;
}
void dfs1(int u) {
siz[u] = ;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dfs1(v);
siz[u] += siz[v];
if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;
}
}
void dfs2(int u,int top) {
bel[u] = top;
xl[u] = ++Index;
if (!son[u]) return ;
dfs2(son[u], top);
for (int i = head[u]; i; i = e[i].nxt)
if (e[i].to != son[u]) dfs2(e[i].to, e[i].to);
}
void add(int x) {
while (x) {
update(, n, , xl[bel[x]], xl[x]);
x = fa[bel[x]];
}
}
int query(int x) {
int ans = ;
while (x) {
ans = (ans + query(, n, , xl[bel[x]], xl[x])) % mod;
x = fa[bel[x]];
}
return ans;
}
int main() {
n = read();int m = read();
for (int i = ; i <= n; ++i) {
fa[i] = read() + ;
add_edge(fa[i], i);
}
dfs1();
dfs2(, );
for (int i = ; i <= m; ++i) {
int l = read() + , r = read() + , z = read() + ;
Que[r].push_back(pa(z, i));
Que[l - ].push_back(pa(z, -i));
}
for (int i = ; i <= n; ++i) {
add(i);
for (int sz = Que[i].size(), j = ; j < sz; ++j) {
if (Que[i][j].second < ) ans[-Que[i][j].second] -= query(Que[i][j].first);
else ans[Que[i][j].second] += query(Que[i][j].first);
}
}
for (int i = ; i <= m; ++i) printf("%d\n", (ans[i] + mod) % mod);
return ;
}
P4211 [LNOI2014]LCA的更多相关文章
- P4211 [LNOI2014]LCA LCT
P4211 [LNOI2014]LCA 链接 loj luogu 思路 多次询问\(\sum\limits_{l \leq i \leq r}dep[LCA(i,z)]\) 可以转化成l到r上的点到根 ...
- 洛谷 P4211 [LNOI2014]LCA 解题报告
[LNOI2014]LCA 题意 给一个\(n(\le 50000)\)节点的有根树,询问\(l,r,z\),求\(\sum_{l\le i\le r}dep[lca(i,z)]\) 一直想启发式合并 ...
- 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)
题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...
- Luogu P4211 [LNOI2014]LCA
我去这道题的Luogu评级是假的吧,这都算黑题. 我们首先考虑把操作离线不强制在线的题目离线一下一般都要方便些 考虑差分,我们用\(f(x)\)表示\([1,x]\)之间的点与\(z\)的答案,那么显 ...
- 并不对劲的bzoj3626:loj2558:p4211:[LNOI2014]LCA
题目大意 有一棵有\(n\)(\(n\leq5*10^4\))个点的树,\(q\)(\(q\leq5*10^4\))次询问,每次给出\(l,r,x\)表示询问所有编号在\([l,r]\)的点与点\(x ...
- 洛谷$P4211\ [LNOI2014]\ LCA$ 树链剖分+线段树
正解:树剖+线段树 解题报告: 传送门$QwQ$ 看到$dep[lca]$啥的就想到之前托腮腮$CSP$模拟$D1T3$的那个套路,,, 然后试下这个想法,于是$dep[lca(x,y)]=\sum_ ...
- [火星补锅] 非确定性有穷状态决策自动机练习题Vol.3 T3 && luogu P4211 [LNOI2014]LCA 题解
前言: 这题感觉还是很有意思.离线思路很奇妙.可能和二次离线有那么一点点相似?当然我不会二次离线我就不云了. 解析: 题目十分清真. 求一段连续区间内的所有点和某个给出的点的Lca的深度和. 首先可以 ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
随机推荐
- django中的字段类型
from http://www.cnblogs.com/lhj588/archive/2012/05/24/2516040.html Django 通过 models 实现数据库的创建.修改.删除等操 ...
- UNIX高级环境编程(7)标准IO函数库 - 二进制文件IO,流定位,创建临时文件和内存流
1 二进制IO(Binary IO) 在前一篇我们了解了逐字符读写和逐行读写函数. 如果我们在读写二进制文件,希望以此读写整个文件内容,这两个函数虽然可以实现,但是明显会很麻烦且多次循环明显效率很低. ...
- 审计系统---堡垒机项目之用户交互+session日志写入数据库[完整版]
2018-06-20 时隔一个多月,忘记了之前的所有操作,重拾起来还是听不容易的,想过放弃,但还是想坚持一下,加油. 世界杯今天葡萄牙1:0战胜摩洛哥,C 罗的一个头球拯救了时间,目前有4个射球,居2 ...
- App案例分析——XBMC
本文分析app的是安卓本地视频播放器:XBMC. 第一部分: 调研,评测 1.下载软件并使用起来,描述最简单直观的个人第一次上手体验. 第一次使用这个播放器,就很喜欢这个主界面,其他类似软件的主界 ...
- Promise & Deferred objects in JavaScript Pt.1: Theory and Semantics.
原文:http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semanti ...
- Spring源码分析之IOC容器(一)
Spring作为当今风靡世界的Web领域的第一框架,作为一名Java开发程序员是一定要掌握的,除了需要掌握基本的使用之外,更需要掌握其实现原理,因为我们往往在开发的过程中,会出现各种各样的异常问题.而 ...
- jQuery事件处理
浏览器的事件模型 DOM第0级事件模型 Event实例 他的属性提供了关于当前正被处理的已触发事件的大量信息.这包括一些细节,比如在哪个元素上触发的事件.鼠标事件的坐标以及键盘事件中单击了哪个键. 事 ...
- 【转】numpy-array自带的迭代器-----np.nditer
转自:https://www.jianshu.com/p/f2bd63766204 it = np.nditer(x, flags=['multi_index'], op_flags=['readwr ...
- Linux 无法连接网络排查方法
.hosts文件增加 127.0.0.1 对localhost的解析. .检查/etc/resove.cnf dns配置是否正确 .route命令检查是否有默认路由,没有就 route add 网段 ...
- 【PHP函数】json_decode() ---- 对 JSON 格式的字符串进行解码
json_decode() --- 对 JSON 格式的字符串进行解码 1.用法: mixed json_decode ( string $json [, bool $assoc = false [, ...