「SCOI2015」情报传递
「SCOI2015」情报传递
题目描述
奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有 \(n\) 名情报员。每名情报员可能有若干名(可能没有)下线,除 \(1\) 名大头目外其余 \(n - 1\) 名情报员有且仅有 \(1\) 名上线。奈特公司纪律森严,每名情报员只能与自己的上、下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递情报。
奈特公司每天会派发以下两种任务中的一个任务:
- 搜集情报:指派 \(T\) 号情报员搜集情报;
- 传递情报:将一条情报从 \(X\) 号情报员传递给 \(Y\) 号情报员。
情报员最初处于潜伏阶段,他们是相对安全的,我们认为此时所有情报员的危险值为 \(0\);一旦某个情报员开始搜集情报,他的危险值就会持续增加,每天增加 \(1\) 点危险值。传递情报并不会使情报员的危险值增加。
为了保证传递情报的过程相对安全,每条情报都有一个风险控制值 \(C\)。余特公司认为,参与传递这条情报的所有情报员中,危险值大于 \(C\) 的情报员将对该条情报构成威胁。现在,奈特公司希望知道,对于每个传递情报任务,参与传递的情报员有多少个,其中对该条情报构成威胁的情报员有多少个。
\(n≤2×10^5,Q≤2×10^5,0<P_i,C_i≤N,1≤T_i,X_i,Y_i≤n\)
解题思路 :
观察发现,只有在第 $ i-C_i-1$ 天之前搜集情报的节点才可能对答案产生贡献
那么问题就转化为点权 $+1 $,和求某一时刻树上一条链上的点权和
比较简单的做法就是将询问离线下来树链剖分即可,复杂度是 $O(nlog^2n) $,而且不能做强制在线
考虑到询问某一时刻其实就是访问历史版本,那么只需要对树上的点权信息进行可持久化即可
记 \(sum_i\) 表示某一时刻 \(i\) 到 \(root\) 的路径的点权和,那么答案就是 \(sum_x + sum_y - sum_{lca} - sum_{fa(lca)}\)
也就是说只要对 \(sum\) 数组可持久化就好了,显然每一次新建一个版本时一个子树的点权都会 \(+1\) ,这东西在 \(dfn\) 序上是一段连续的区间,直接 \(ins\) 即可,总复杂度是 $O(nlogn) $
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define fi first
#define se second
const int N = 200005;
vector<int> g[N];
int rt[N], sz[N], ds[N], dep[N], dfn[N], f[N][21], vis[N], n, m, cnt, root;
namespace Prework{
inline void dfs(int u, int fa){
sz[u] = 1, f[u][0] = fa, dep[u] = dep[fa] + 1, dfn[u] = ++cnt;
for(int i = 0; i < g[u].size(); i++)
if(g[u][i] != fa) dfs(g[u][i], u), sz[u] += sz[g[u][i]];
}
inline void realmain(){
dfs(root, 0);
for(int j = 1; j <= 20; j++)
for(int i = 1; i <= n; i++) f[i][j] = f[f[i][j-1]][j-1];
}
}
inline pair<int, int> Getpath(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
for(int i = 20; ~i; i--){
if(dep[f[x][i]] >= dep[y]) x = f[x][i];
if(dep[x] == dep[y]) break;
}
if(x == y) return make_pair(x, f[x][0]);
for(int i = 20; ~i; i--)
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return make_pair(f[x][0], f[f[x][0]][0]);
}
struct SegmentTree{
struct Node{ int lc, rc, add; } T[N*50]; int size;
inline void ins(int &u, int pr, int l, int r, int L, int R){
T[u=++size] = T[pr];
if(l >= L && r <= R) return (void) (T[u].add++);
int mid = l + r >> 1;
if(L <= mid) ins(T[u].lc, T[pr].lc, l, mid, L, R);
if(mid < R) ins(T[u].rc, T[pr].rc, mid + 1, r, L, R);
}
inline int query(int u, int l, int r, int pos){
if(l == r) return T[u].add;
int mid = l + r >> 1, res = 0;
if(pos <= mid) res += query(T[u].lc, l, mid, pos);
else res += query(T[u].rc, mid + 1, r, pos);
return res + T[u].add;
}
}van;
inline int calc(int x, int y){
if(!dfn[y] || !ds[x]) return 0;
return van.query(rt[ds[x]], 1, n, dfn[y]);
}
int main(){
read(n);
for(int i = 1, x; i <= n; i++){
read(x);
if(x) g[x].push_back(i), g[i].push_back(x); else root = i;
}
Prework::realmain();
read(m);
for(int i = 1, op, x, y, z; i <= m; i++){
read(op), read(x);
if(op == 1){
ds[i] = ds[i-1], read(y), read(z); int t = Max(i - z - 1, 0);
pair<int, int> now = Getpath(x, y);
int res = calc(t, x) + calc(t, y) - calc(t, now.fi) - calc(t, now.se);
printf("%d %d\n", dep[x] + dep[y] - dep[now.fi] - dep[now.se], res);
}
else{
if(vis[x]){ ds[i] = ds[i-1]; continue; }
ds[i] = ds[i-1] + 1, vis[x] = 1;
van.ins(rt[ds[i]], rt[ds[i-1]], 1, n, dfn[x], dfn[x] + sz[x] - 1);
}
}
return 0;
}
「SCOI2015」情报传递的更多相关文章
- AC日记——「SCOI2015」情报传递 LiBreOJ 2011
#2011. 「SCOI2015」情报传递 思路: 可持久化树状数组模板: 代码: #include <bits/stdc++.h> using namespace std; #defin ...
- 【LOJ】 #2011. 「SCOI2015」情报传递
题解 一写过一交A的一道数据结构水题 我们发现大于C可以转化为这条路径上有多少个在某天之前开始调查的情报员,离线全部读入,变成树上路径查询某个区间的数出现过多少次,构建一棵根缀的主席树,查询的时候用两 ...
- 「SCOI2015」小凸想跑步 解题报告
「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...
- 「SCOI2015」国旗计划 解题报告
「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...
- 「SCOI2015」小凸解密码 解题报告
「SCOI2015」小凸解密码 题意:给一个环,定义一段连续的极长\(0\)串为\(0\)区间,定义一个位置的离一个\(0\)区间的距离为这个位置离这个区间中\(0\)的距离的最小值,每次询问一个位置 ...
- 「SCOI2015」小凸玩矩阵 解题报告
「SCOI2015」小凸玩矩阵 我好沙茶啊 把点当边连接行和列,在外面二分答案跑图的匹配就行了 我最开始二分方向搞反了,样例没过. 脑袋一抽,这绝壁要费用流,连忙打了个KM 然后wa了,一想这个不是完 ...
- 「SCOI2015」小凸玩密室 解题报告
「SCOI2015」小凸玩密室 虽然有心里在想一些奇奇怪怪的事情的原因,不过还是写太久了.. 不过这个题本身也挺厉害的 注意第一个被点亮的是任意选的,我最开始压根没注意到 \(dp_{i,j}\)代表 ...
- loj#2009.「SCOI2015」小凸玩密室
题目链接 loj#2009. 「SCOI2015」小凸玩密室 题解 树高不会很高<=20 点亮灯泡x,点亮x的一个子树,再点亮x另外的子树, 然后回到x的父节点,点亮父节点之后再点亮父节点的其他 ...
- LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配
#2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
随机推荐
- python学习笔记(十五)之集合
集合:对应数学中的集合类型.集合中的元素是唯一,且无序的. 创建集合 方法一:使用{},注意python会自动删除重复元素 >>> number = {1,2,3,4,3,2,1} ...
- 读书笔记 ~ Nmap渗透测试指南
记录Nmap选项及脚本使用,仅供参考... 除了端口扫描,好像其它脚本都比较鸡肋,用途感觉应该没有专用的小工具好用,不过还是可以看看,选项和脚本还是相当的丰富的. Nmap 使用帮助 starnigh ...
- 使用webpack配置react并添加到flask应用
学习react,配置是很痛苦的一关,虽然现在有了create-react-app这样方便的工具,但是必须要自己配置一遍,才能更好地进行项目开发. 首先要明确一个概念:react的文件必须经过编译才能被 ...
- 33、re的match和search区别?
1.match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配:2.也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功 ...
- Machine Learning系列--维特比算法
维特比算法(Viterbi algorithm)是在一个用途非常广的算法,本科学通信的时候已经听过这个算法,最近在看 HMM(Hidden Markov model) 的时候也看到了这个算法.于是决定 ...
- LINUX内核中的机制OOM
[概念] LINUX内核中有一个机制叫做OOM killer(Out Of Memery killer) 该机制监控内存占用过大,尤其是瞬间消耗大量内存的进程, 为了防止内存被耗尽,所以OOM kil ...
- maven实战系列
Maven实战(一)安装和配置 Maven实战(二)构建简单Maven项目 Maven实战(三)Eclipse构建Maven项目 Maven实战(四)生命周期 Maven实战(五)坐标详解 Maven ...
- 详解Oracle的unlimited tablespace系统权限
1. 系统权限unlimited tablespace是隐含在dba, resource角色中的一个系统权限. 当用户得到dba或resource的角色时, unlimited tablespace系 ...
- ECMA-Script5
严格模式 所谓严格模式,从字面上就很好理解,即更严格的模式 在这种模式下执行,浏览器会对JS的要求更苛刻. 举例: function m1(){ max = 100; } m1(); al ...
- DOM的查找与操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...