「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标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
随机推荐
- 【BZOJ】1426: 收集邮票 期望DP
[题意]有n种不同的邮票,第i次可以花i元等概率购买到一种邮票,求集齐n种邮票的期望代价.n<=10^4. [算法]期望DP [题解]首先设g[i]表示已拥有i张邮票集齐的期望购买次数,根据全期 ...
- NYOJ 117 求逆序数 (树状数组)
题目链接 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出 ...
- python3爬虫.4.下载煎蛋网妹子图
开始我学习爬虫的目标 ----> 煎蛋网 通过设置User-Agent获取网页,发现本该是图片链接的地方被一个js函数代替了 于是全局搜索到该函数 function jandan_load_im ...
- JS设计模式——2.初识接口
什么是接口 接口提供了一种用以说明一个对象应该具有哪些方法的手段. 接口之利 1.接口具有自我描述性从而促进代码的重用 2.接口有助于稳定不同中的类之间的通信方式 3.测试和调试也变得更轻松 接口之弊 ...
- c++中指针常量,常指针,指向常量的常指针区分
const char * myPtr = &char_A;//指向常量的指针 char * const myPtr = &char_A;//常量的指针 const char * con ...
- weblogic 开启注意问题
1.关闭防火墙 service iptables stop chkconfig iptables off 2.weblogic unable to get file lock问题 我的解决办法是ps ...
- 37 - 网络编程-UDP编程
目录 1 UDP协议 2 UDP通信流程 3 UDP编程 3.1 构建服务端 3.3 常用方法 4 聊天室 5 UDP协议应用 1 UDP协议 UDP是面向无连接的协议,使用UDP协议时,不需要建立连 ...
- 【Windows使用笔记】神舟笔记本的control center
首先,神船大法好. 然后,因为我的船风扇声音有点大啊,在实验室感觉就很吵,但是它的背板温度又不是很高,所以想设置下风扇的启动. 所以需要用到神船自带的control center软件. 长这样. 应该 ...
- LDA线性判别分析
LDA线性判别分析 给定训练集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能的近,异类样例点尽可能的远,对新样本进行分类的时候,将新样本同样的投影,再根据投影得到的位置进行判断,这个新样本的 ...
- python基础===如何在列表,字典,集合中根据条件筛选数据
#常见的操作如下: data = [1, 5, -3, -2, 6, 0, 9] res = [] for x in data: if x>=0: res.append(x) print(res ...