「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标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
随机推荐
- 更改gradle的java的class文件输出目录的结构
group 'com.thinkvenus.common'version '1.0-SNAPSHOT' apply plugin: 'java' sourceCompatibility = 1.8 r ...
- [csp-201809-3]元素选择器-编译原理
声明:同样是参考照抄hyh学长的代码!(有问题我马上删这篇emm 题目链接:http://118.190.20.162/view.page?gpid=T77 题面: 这棵树的样子(同样是来自学长的图) ...
- Please move or remove them before you can merge
在使用git pull时,经常会遇到报错: Please move or remove them before you can merge 这是因为本地有修改,与云端别人提交的修改冲突,又没有merg ...
- 在eclipse安装mybatis的插件
1.在help中打开 2.搜索mybatipse 3:功能简介 1:要查找某一个方法 在dao接口中某一个方法中 按住 Ctrl键 鼠标指到方法名称上 选择open xml 就会自动跳转 ...
- flume监控一个linux指定的一个文件夹的文件信息
1.编辑一个配置文件 flume-app.conf 拷贝至fulme的安装目录的conf下 # The configuration file needs to define the sources, ...
- 二. Jmeter--关联
1. 首先建立一个线程组(Thread Group),为什么所有的请求都要加入线程组这个组件呢?不加不行吗?答案当然是不行的.因为jmeter的所有任务都必须由线程处理,所有任务都必须在线程组下面创建 ...
- MongoDB之安装和基本使用(一)
环境 ubuntu16.04 mongodb基本特点 MongoDB 是一个基于分布式 文件存储的NoSQL数据库;可以把MongoDB想象成一个大py字典. 模式自由 :可以把不同结构的文档存储在同 ...
- Linux下的lds链接脚本详解【转】
转自:http://www.cnblogs.com/li-hao/p/4107964.html 转载自:http://linux.chinaunix.net/techdoc/beginner/2009 ...
- (转)USB 基本知识
USB的重要关键字: 1.端点:位于USB设备或主机上的一个数据缓冲区,用来存放和发送USB的各种数据,每一个端点都有惟一的确定地址,有不同的传输特性(如输入端点.输出端点.配置端点.批量传输端点) ...
- Hibernate根据配置文件,生成建表语句
import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; public class ...