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 ;
}

最新文章

  1. 【WebGoat习题解析】Parameter Tampering-&gt;Bypass HTML Field Restrictions
  2. SWT: 发起事件 post event
  3. API 开发实践
  4. Repeater控件 ---属性(ItemCommand事件)
  5. 2次成功投诉EMS和中国移动的经验
  6. Eclipse如何生成带有自定tag的Java Doc
  7. -canOpenURL: failed for URL
  8. IsPostBack是什么意思,如何运用?
  9. 三思考,实现自己定义404页:Tomcat、SpringMVC精确匹配、重写DispatchServlet
  10. RabbitMQ 消息队列 配置
  11. Kubernetes 架构(上)- 每天5分钟玩转 Docker 容器技术(120)
  12. ARouter学习随笔
  13. MySQL数据库引擎类别和更换方式
  14. 【hdu6186】CS Course(前缀后缀异或)
  15. bzoj1040 基环树森林dp
  16. pt站 扫盲贴 面向小白
  17. MyDO
  18. libev
  19. Codeforces Round #370 (Div. 2) A. Memory and Crow 水题
  20. linq to xml 初学 -- 查询语法

热门文章

  1. 关于sys CPU usage 100%问题的分析
  2. 用block将UIAlertView与UIActionSheet统一起来
  3. centos7.4应用之KVM
  4. windows 2012R2 上必须要用sharepoint 2013 sp1.
  5. ZT eoe android4.2 Bluetooth记录01-结构和代码分布
  6. 破解myeclipse10失败的一个奇葩原因
  7. Redis info参数总结
  8. vue 校验插件 veeValidate使用
  9. 安装VMware,Linux
  10. [CEOI2017]Building Bridges