当前位置: 首页 > news >正文

P4211 [LNOI2014] LCA

P4211 [LNOI2014] LCA

大意

P4211 [LNOI2014] LCA

题目描述

\(m\) 次询问,每次询问给出 \(l, r, z\),求 \(\sum_{i=l}^r dep[\operatorname{LCA}(i,z)]\)

思路

好题啊,首先我们想到一个很重要的问题,这个东西在 \(z\) 固定的情况下,其实与 \(l, r\) 并没有太大的关系,我们是可以差分处理的,直接计算 \(\sum_{i = 0} ^ {r} dep[\operatorname{LCA}(i, z)] - \sum_{i = 0} ^ {l - 1} dep[\operatorname{LCA}(i, z)]\)

但是这样还是复杂度爆炸,我们需要进一步优化,考虑扫描线,我们如果直接把每次的询问 \([l, r]\) 划分为两个事件 \(l - 1\)\(r\) ,这样一来,我们将这 \(m\) 个事件拆分为 \(2m\) 个事件,我们把这些事件按拆分出来的 pos 排序,然后按顺序处理这些询问,注意记录是 \(l - 1\) 还是 \(r\),这两种的符号是不一样的。

代码

#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int N = 100000 + 10;
const int MOD = 201314;
vector<int> g[N];
int n, m;
int par[N], son[N], sz[N], dep[N];
int top[N], dfn[N], who[N], CLOCK;#define lc (rt << 1)
#define rc (rt << 1 | 1)void pre(int u, int p, int d){par[u] = p, son[u] = -1, sz[u] = 1, dep[u] = d;int mx = 0;for(int i = 0;i < g[u].size();i ++){int v = g[u][i];if(p == v) continue;pre(v, u, d + 1);sz[u] += sz[v];if(sz[v] > mx){mx = sz[v], son[u] = v;}}
}void dfs(int u, int p){top[u] = p, dfn[u] = ++ CLOCK;if(son[u] != -1){dfs(son[u], p);}for(int i = 0;i < g[u].size();i ++){int v = g[u][i];if(v == son[u] || v == par[u]){continue;}dfs(v, v);}
}int sum[N << 2], lz[N << 2];
void pushdown(int rt, int l, int r){if(lz[rt]){int mid = (l + r) >> 1;lz[lc] = (lz[lc] + lz[rt]) % MOD;sum[lc] = (sum[lc] + (mid - l + 1LL) * lz[rt]) % MOD;lz[rc] = (lz[rc] + lz[rt]) % MOD;sum[rc] = (sum[rc] + (r - mid + 0LL) * lz[rt]) % MOD;lz[rt] = 0;}
}void update(int l, int r, int rt, int L, int R, int x){if(L <= l && r <= R){lz[rt] = (lz[rt] + x) % MOD;sum[rt] = (sum[rt] + (r - l + 1LL) * x) % MOD;return;}int mid = (l + r) >> 1;pushdown(rt, l, r);if(L <= mid) update(l, mid, lc, L, R, x);if(R > mid) update(mid + 1, r, rc, L, R, x);sum[rt] = (sum[lc] + sum[rc]) % MOD;
}int query(int l, int r, int rt, int L, int R){if(L <= l && r <= R){return sum[rt];}int mid = (l + r) >> 1, ans = 0;pushdown(rt, l, r);if(L <= mid){ans = (ans + query(l, mid, lc, L, R)) % MOD;}if(R > mid){ans = (ans + query(mid + 1, r, rc, L, R)) % MOD;}return ans;
}void pathC(int u, int x){int v = 0;while(top[u] != top[v]){if(dep[top[u]] < dep[top[v]]) swap(u, v);update(1, n, 1, dfn[top[u]], dfn[u], x);u = par[top[u]];}if(dep[u] > dep[v]) swap(u, v);update(1, n, 1, dfn[u], dfn[v], x);
}int pathS(int u){int v = 0, ans = 0;while(top[u] != top[v]){if(dep[top[u]] < dep[top[v]]) swap(u, v);ans = (ans + query(1, n, 1, dfn[top[u]], dfn[u])) % MOD;u = par[top[u]];}if(dep[u] > dep[v]) swap(u, v);ans = (ans + query(1, n, 1, dfn[u], dfn[v])) % MOD;return ans;
}struct node{int pos, z, id, sign;bool operator < (const node &b)const{return pos < b.pos;}
}q[N << 1];
int Ans[N];int main(){scanf("%d%d", &n, &m);for(int i = 1;i < n;i ++){int p; scanf("%d", &p);g[p].push_back(i);}pre(0, 0, 1);dfs(0, 0);int cnt = 0;for(int i = 1;i <= m;i ++){int l, r, z; scanf("%d%d%d", &l, &r, &z);q[++ cnt] = {l - 1, z, i, -1};q[++ cnt] = {r, z, i, 1};}sort(q + 1, q + cnt + 1);int cur = -1;for(int i = 1;i <= cnt;i ++){while(cur < q[i].pos){pathC(++ cur, 1);}int res = pathS(q[i].z);if(q[i].sign == 1) Ans[q[i].id] = (Ans[q[i].id] + res) % MOD;else Ans[q[i].id] = (Ans[q[i].id] - res + MOD) % MOD;}for(int i = 1;i <= m;i ++){printf("%d\n", Ans[i]);}return 0;
}
http://www.jsqmd.com/news/394983/

相关文章:

  • 蓝牙低功耗音频 Le audio音频输入控制协议(AICS)剖析 - 指南
  • 亲身经历:月薪五千,如何应对十万逾期债务?性价比高的协商路子在这 - 代码非世界
  • 题解:洛谷 P2196 [NOIP 1996 提高组] 挖地雷
  • AI应用架构师总结:在线学习系统架构设计的8个核心文档
  • 提示工程架构师亲授:智能交通中的5个关键Prompt设计
  • 本地贷款逾期协商较好的机构口碑评价较高的信用卡协商机构 - 代码非世界
  • 探秘AI提示工程架构师在智能营销中的提示工程应用
  • 贷款逾期真实的网上委托协商还款机构有哪些推荐? - 代码非世界
  • Agent 架构下的沙盒隔离技术实现
  • 题解:洛谷 P1216 [IOI 1994 / USACO1.5] 数字三角形 Number Triangles
  • 贷款逾期后,协商还款可以找哪些机构?协商还款找对这3类机构,稳步上岸不踩坑 - 代码非世界
  • AI原生应用领域:混合推理对行业的变革影响
  • 亚洲:出境游/短期出国福音:eSIM卡使用体验与RedteaGo套餐推荐
  • SpringBoot vs SpringMVC:以及SpringBoot的全流程开发(1)
  • 在飞牛 NAS(fnOS)上使用 Docker 部署 FastAPI 应用(这个是从错误学习教程 图是可以的)
  • OpenAI 和 Paradigm 推出 EVMbench:AI 帮智能合约把关的新工具
  • 题解:洛谷 P2341 [USACO03FALL / HAOI2006] 受欢迎的牛 G
  • 题解:洛谷 P3387 【模板】缩点
  • 信用卡逾期不用慌!实测口碑债务协商机构推荐,负债人安心上岸指南 - 代码非世界
  • 从0学习pwn【第三章】剖析ret2text32位,从函数调用到gdb调试(1)
  • 题解:洛谷 P3388 【模板】割点(割顶)
  • 题解:洛谷 P2860 [USACO06JAN] Redundant Paths G
  • 详细介绍:幽冥大陆(一百10)PHP打造Java的Jar安全——东方仙盟筑基期
  • ARM-中断管理
  • 题解:洛谷 P1656 炸铁路
  • 题解:洛谷 P2863 [USACO06JAN] The Cow Prom S
  • 告别“打字机”:Generative UI 如何重塑 AI 时代的前端交互?
  • DataFrame条件筛选:从入门到实战的数据清洗利器
  • 题解:洛谷 P2700 逐个击破
  • DataFrame数据修改:从基础操作到高效实践的完整指南