原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ407.html

题解

套路啊。

先按照两个节点顺序各搞一个kruskal重构树,然后问题转化成两棵kruskal重构树,不断询问,每次询问让你判断是否有点同时存在于 第一棵树的一个子树 和 第二棵树的一个子树中。

这个东西就转成dfs序之后主席树搞一搞就好了。

代码

#include <bits/stdc++.h>
#include "werewolf.h"
#define clr(x) memset(x,0,sizeof (x))
#define y1 __zzd001
using namespace std;
typedef vector <int> vi;
const int N=400005;
int n,m,q;
vi e[N],ans,tmp;
namespace ufs{
int fa[N];
void init(int n){
for (int i=1;i<=n;i++)
fa[i]=i;
}
int getf(int x){
return fa[x]==x?x:fa[x]=getf(fa[x]);
}
}
struct ktree{
int val[N],son[N][2],fa[N][20];
int I[N],O[N],vis[N];
int cnt,root,Time;
void dfs(int x){
if (!x)
return;
I[x]=++Time;
for (int i=1;i<20;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
dfs(son[x][0]);
dfs(son[x][1]);
O[x]=Time;
}
void build(vi ord){
clr(val),clr(son),clr(fa),clr(vis);
cnt=n;
ufs::init(n*2);
for (auto x : ord){
val[x]=x,vis[x]=1;
for (auto y : e[x]){
if (!vis[y])
continue;
int fx=ufs::getf(x),fy=ufs::getf(y);
if (fx==fy)
continue;
val[++cnt]=x;
ufs::fa[fx]=ufs::fa[fy]=fa[fx][0]=fa[fy][0]=cnt;
son[cnt][0]=fx,son[cnt][1]=fy;
}
}
for (root=1;fa[root][0];root=fa[root][0]);
Time=0;
dfs(root);
}
}t1,t2;
int c1,c2;
namespace pt{
const int S=N*40;
int val[S],ls[S],rs[S],root[N],cnt,m;
int build(int L,int R){
int rt=++cnt;
if (L==R)
return rt;
int mid=(L+R)>>1;
ls[rt]=build(L,mid);
rs[rt]=build(mid+1,R);
return rt;
}
void init(int _m){
clr(val),clr(ls),clr(rs),clr(root),cnt=0;
root[0]=build(1,m=_m);
}
void update(int prt,int &rt,int L,int R,int x){
if (!rt||rt==prt)
rt=++cnt,val[rt]=val[prt],ls[rt]=ls[prt],rs[rt]=rs[prt];
val[rt]++;
if (L==R)
return;
int mid=(L+R)>>1;
if (x<=mid)
update(ls[prt],ls[rt],L,mid,x);
else
update(rs[prt],rs[rt],mid+1,R,x);
}
int Query(int prt,int rt,int L,int R,int xL,int xR){
if (xR<L||R<xL)
return 0;
if (xL<=L&&R<=xR)
return val[rt]-val[prt];
int mid=(L+R)>>1;
return Query(ls[prt],ls[rt],L,mid,xL,xR)
+Query(rs[prt],rs[rt],mid+1,R,xL,xR);
}
int Query(int x1,int x2,int y1,int y2){
return Query(root[x1-1],root[x2],1,m,y1,y2);
}
}
vi check_validity(int n,vi X,vi Y,vi S,vi E,vi L,vi R){
::n=n,m=(int)X.size(),q=(int)S.size(),ans.clear();
for (int i=0;i<m;i++)
X[i]++,Y[i]++;
for (int i=0;i<q;i++)
S[i]++,E[i]++,L[i]++,R[i]++;
for (int i=1;i<=n;i++)
e[i].clear();
for (int i=0;i<m;i++){
e[X[i]].push_back(Y[i]);
e[Y[i]].push_back(X[i]);
}
tmp.clear();
for (int i=1;i<=n;i++)
tmp.push_back(i);
t1.build(tmp),t1.val[0]=1e9;
reverse(tmp.begin(),tmp.end());
t2.build(tmp),t2.val[0]=-1e9;
c1=t1.cnt,c2=t2.cnt;
tmp.resize(c1+1);
for (int i=1;i<=c1;i++)
tmp[t1.I[i]]=i;
pt::init(c2);
for (int i=1;i<=c1;i++){
int x=tmp[i];
pt::root[i]=pt::root[i-1];
if (x<=n)
pt::update(pt::root[i-1],pt::root[i],1,pt::m,t2.I[x]);
}
for (int i=0;i<q;i++){
int x=S[i],y=E[i],l=L[i],r=R[i];
if (x<l||y>r){
ans.push_back(0);
continue;
}
for (int i=19;i>=0;i--){
if (t2.val[t2.fa[x][i]]>=l)
x=t2.fa[x][i];
if (t1.val[t1.fa[y][i]]<=r)
y=t1.fa[y][i];
}
int t=pt::Query(t1.I[y],t1.O[y],t2.I[x],t2.O[x]);
ans.push_back(t?1:0);
}
return ans;
}

  

UOJ#407. 【IOI2018】狼人 Kruskal,kruskal重构树,主席树的更多相关文章

  1. luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)

    题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...

  2. LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)

    LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...

  3. [IOI2018] werewolf 狼人 [kruskal重构树+主席树]

    题意: 当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点) 当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点) 然后问题转化成人形和狼形能到的点 ...

  4. Luogu4899 IOI2018狼人(kruskal重构树+主席树)

    可以发现询问的即是“由起点开始‘只经过编号大于等于l的点’所形成的连通块”与“由终点开始‘只经过编号小于等于r的点’所形成的连通块”是否有交集.于是建出重构树,就可以知道每个询问的连通情况了.现在要知 ...

  5. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  6. BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增

    题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...

  7. luogu4197 Peaks (kruskal重构树+主席树)

    按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...

  8. 洛谷P4197 Peaks(Kruskal重构树 主席树)

    题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...

  9. [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)

    3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2438  Solved: 763[Submit][ ...

随机推荐

  1. 11.2 Flask 配置文件,路由系统

    配置文件系统 构建 Flask 应用时指定 app = Flask( __name__, template_folder = '', # 指定存储模板文件夹名称 static_url_path = ' ...

  2. [https]公司导入自签名证书实现https监控

    https://www.v2ex.com/t/143012

  3. Vim和Neovim安装YouCompleteMe

    确定支持Python,Vim一般支持,Neovim默认不支持 Vim的就不介绍方法了,很多系统都不一样.Neovim添加Python支持 pip install setuptools pip inst ...

  4. (二分查找 结构体) leetcode33. Search in Rotated Sorted Array

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  5. Django-ContentType的使用

    一.神器ContentType 如果 继续增加课程 价格策略表还得增加字段 这样django自带一个contentType 帮助我们解决表之间的依赖关系: 1.从settings文件可以看到原生就支持 ...

  6. Mybatis的原理与JVM内存结构(面试题)

    Mybatis的原理 1.Mapper 接口在初始SQL SessionFactory注册的 2.Mapper 接口注册在名为MapperRegistry类的 HasMap中 key=Mapper c ...

  7. Docker:跨主机容器间通信之overlay [十五]

    一.配置overlay类型网络准备工作 1.在luoahong3主机上 docker run -d -p 8500:8500 -h consul --name consul progrium/cons ...

  8. Java进程线程笔记

    什么是并行和并发? 并发和并行是即相似又有区别:(微观) 并行:指两个或多个事件在同一时刻发生: 强调的是时间点. 并发:指两个或多个事件在同一时间段内发生: 强调的是时间段. 进程和线程的区别? 进 ...

  9. Java虚拟机垃圾回收(三) 7种垃圾收集器

    Java虚拟机垃圾回收(三) 7种垃圾收集器 主要特点 应用场景 设置参数 基本运行原理 在<Java虚拟机垃圾回收(一) 基础>中了解到如何判断对象是存活还是已经死亡?在<Java ...

  10. JGUI源码:从头开始,建一个自己的UI框架(1)

    开篇 1.JGUI是为了逼迫自己研究底层点的前端技术而做的框架,之前对web底层实现一直没有深入研究,有了技术瓶颈,痛定思痛从头研究, 2.虽然现在vue技术比较火,但还在发展阶段,暂时先使用JQue ...