UOJ#407. 【IOI2018】狼人 Kruskal,kruskal重构树,主席树
原文链接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重构树,主席树的更多相关文章
- luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)
题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...
- LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...
- [IOI2018] werewolf 狼人 [kruskal重构树+主席树]
题意: 当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点) 当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点) 然后问题转化成人形和狼形能到的点 ...
- Luogu4899 IOI2018狼人(kruskal重构树+主席树)
可以发现询问的即是“由起点开始‘只经过编号大于等于l的点’所形成的连通块”与“由终点开始‘只经过编号小于等于r的点’所形成的连通块”是否有交集.于是建出重构树,就可以知道每个询问的连通情况了.现在要知 ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- luogu4197 Peaks (kruskal重构树+主席树)
按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...
- 洛谷P4197 Peaks(Kruskal重构树 主席树)
题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
随机推荐
- jmeter5.1测试dubbo接口
dubbo接口功能介绍 客户端输入uncleyong(当然,也可以是其他字符串),服务端返回hello uncleyong 开发dubbo服务jmeter客户端 idea中创建模块dubbo_jmet ...
- Docker容器进入的4种方式
Docker容器进入的4种方式 $ sudo docker ps $ sudo docker exec -it 775c7c9ee1e1 /bin/bash 在使用Docker创建了容器之后,大家比较 ...
- 走进Java中的持有对象(容器类)之一 容器分类
Java容器可以说是增强程序员编程能力的基本工具,本系列将带您深入理解容器类. 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 ...
- 金融量化分析【day110】:NumPy多维数组
一.Numpy简介 NumPy 是高性能科学计算和数据分析的基础包,它是pandas等其他各种工具的基础 1.主要功能 1.ndarray,一个多维数组结构,高效且节省空间 2.无序循环对整组数据进行 ...
- word插入公式不自动斜体的解决办法
1.word-视图-宏 2.自己随便输入一个宏名,比如就叫InsertEqua,然后将 Sub InsertEqua() Selection.OMaths.Add Range:=Selection.R ...
- 树链剖分详解(洛谷模板 P3384)
洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...
- javascript基础 之 表单
1,js可以验证表单 实例1,js获取表单的内容 //html表单是这样的 <form name="myForm" action="demo_form.php&qu ...
- 不用写代码的框架 - RobotFramework+Eclispe环境安装篇
环境安装是学习任何一个新东西的第一步,这一步没走舒坦,那后面就没有心情走下去了. 引用名句:工欲善其事必先利其器!! Robotframework:一款 自动化测试框架. Eclipse:一款编辑工具 ...
- kerbose常用操作
1.查看有那些用户认证 kadmin.local -q "list_principals" 2.用keytab文件进行认证 kinit -kt /root/keytab/hive. ...
- 响应消息的内容类型 text/html; charset=utf-8 与绑定(application/soap+xml; charset=utf-8)的内容类型不匹配。
问题表述: 响应消息的内容类型 text/html; charset=utf-8 与绑定(application/soap+xml; charset=utf-8)的内容类型不匹配. 说明: 此类问题当 ...