LGP4216题解
这是一种题解没有的 \(O(m\log n)\) 做法。
首先第一步转化。设这是第 \(x\) 个任务,若 \(opt\) 为 \(1\),危险值大于 \(c\) 的只有可能在第 \(x-c-1\) 个任务以前出现。
于是题目就变成了在某一时刻单点加和在某一时刻链上查询,离线即可去掉“某一时刻”。
单点加和链上查询,大家用的应该都是树剖,复杂度是 \(O(\log^2n)\) 的。然而使用 DFS 序和差分,将单点加转化为子树加,将链上查询转化为单点查询。
具体来说就是设一个 \(s[u]\) 表示节点 \(u\) 到根节点有多少个节点是危险的,那么单点加就可以变成子树加,在 DFS 序上就是区间加。
链上查询只需要查询 \(u,v,LCA(u,v),f[LCA(u,v)]\),也就是单点查。
区间加单点查,树状数组上!
极短的代码:
#include<cstdio>
#include<vector>
const int M=2e5+5;
int n,m,dfc,d[M],f[M],dfn[M],siz[M],son[M],top[M];
int BIT[M];int opt[M],x[M],y[M],ans[M];
std::vector<int>G[M],id[M];
void DFS1(int u){
dfn[u]=++dfc;d[u]=d[f[u]]+1;siz[u]=1;
for(int&v:G[u]){
DFS1(v);siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void DFS2(int u,int tp){
top[u]=tp;if(!son[u])return;DFS2(son[u],tp);
for(int&v:G[u])if(v!=son[u])DFS2(v,v);
}
inline int LCA(int u,int v){
while(top[u]^top[v]){
if(d[top[u]]>d[top[v]])u=f[top[u]];
else v=f[top[v]];
}
return d[u]>d[v]?v:u;
}
inline int dis(const int&u,const int&v){
return d[u]+d[v]-(d[LCA(u,v)]<<1)+1;
}
inline void Add(int x,const int&val){
for(;x<=n;x+=1<<__builtin_ctz(x))BIT[x]+=val;
}
inline int Query(int x){
int ans=0;
for(;x>=1;x-=1<<__builtin_ctz(x))ans+=BIT[x];
return ans;
}
inline int Q(const int&x,const int&y){
int lca=LCA(x,y);
return Query(dfn[x])+Query(dfn[y])-Query(dfn[lca])-Query(dfn[f[lca]]);
}
signed main(){
register int i,k;
scanf("%d",&n);
for(i=1;i<=n;++i)scanf("%d",f+i),G[f[i]].push_back(i);
for(i=1;f[i];i=f[i]);
DFS1(i);DFS2(i,i);
scanf("%d",&m);
for(i=1;i<=m;++i){
scanf("%d",opt+i);
if(opt[i]==1){
scanf("%d%d%d",x+i,y+i,&k);
if(k<i)id[i-k-1].push_back(i);
}
if(opt[i]==2){
scanf("%d",x+i);
}
}
for(i=1;i<=m;++i){
if(opt[i]==2){
Add(dfn[x[i]],1);Add(dfn[x[i]]+siz[x[i]],-1);
}
for(int&v:id[i])ans[v]=Q(x[v],y[v]);
if(opt[i]==1){
printf("%d %d\n",dis(x[i],y[i]),ans[i]);
}
}
}
LGP4216题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- Java中float、double、long类型变量赋值添加f、d、L尾缀问题
展开1. 添加尾缀说明 我们知道Java在变量赋值的时候,其中float.double.long数据类型变量,需要在赋值直接量后面分别添加f或F.d或D.l或L尾缀来说明. 其中,long类型最好以 ...
- Java线程--ThreadPoolExecutor使用
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871132.html Java线程--ThreadPoolExecutor使用 public ...
- Shell for&while中的循环
#!/usr/bin/ksh #数字段形式 for i in {1..10} do echo $i done #详细列出(字符且项数不多) for File in 1 2 3 4 5 do echo ...
- NSString 类介绍及用法
1.NSString常见方法 NSString是 Objective-C 中核心处理字符串的类之一 创建常量字符串,注意使用"@"符号. NSString *astring = @ ...
- chmod以数字形式改变文件权限
Linux文件的三种身份和四种权限,三种身份分别为: u:文件的拥有者 g:文件所属的群组 o:其他用户 对于每个身份,又有四种权限,分别为: r:读取文件的权限(read) w:写入文件的权限(wr ...
- MATLAB 机器人学工具箱(Robotics Toolbox )sl_drivepoint 模型 consecutive zero crossings 问题
操作环境 工具箱:Robotics Toolbox for MATLAB 版本 10.2.1 作者 Peter Corke MATLAB版本:R2018a 操作系统:win10 问题 sl_drive ...
- linux c 线程相关函数
线程相关函数(1)-pthread_create(), pthread_join(), pthread_exit(), pthread_cancel() 创建取消线程 一. pthread_creat ...
- Spark算子 - reduce
释义 reduce将partition内所有记录最终计算成1个记录,结果类型与reduce 时数据类型一致 方法签名如下: def reduce(f: (T, T) => T): T = wit ...
- Lesson11——NumPy 位运算
NumPy 教程目录 Lesson11--NumPy 位运算 NumPy "bitwise_" 开头的函数是位运算函数. NumPy 位运算包括以下几个函数: 函数 描述 bitw ...
- MySQL保留2位小数
1.round(x,d),四舍五入.round(x) ,其实就是round(x,0),也就是默认d为0 select round(110.35,1); # 110.4 2.TRUNCATE(x,d), ...