link

题意:

给一张n个点m条边的无向图,有q个询问,每次询问给出s,t,l,r,问你能否从s走到t,并且初始为人形,结束时必须为狼形,你是人形的时候必须避开$[1,l)$的节点,狼形的时候必须避开$(r,n]$的节点,你只能在$[L,R]$的节点处变身?

$n,q\leq  2\times 10^5,m\leq 4\times 10^5.$

题解:

get技能——Kruskal重构树

重构树是一个类似堆的结构,节点u比它的所有儿子v的权都要来的小/大(在这题中都有用到),可以用并查集建树。

考虑题中s~t有合法路径相当于,s只经过L~N的点能到达的点集和t只经过1~R的点能到达的点集有交。

那么考虑建出Kruskal最大/小重构树,那么两个点集分别对应到两棵树上的一个子树,求出dfs序转化成两个区间。

把每个点对应到一个坐标$[dfn1,dfn2]$(在两棵树中dfs序上的位置),原问题等价于询问一个矩形$x∈[l1,r1],y∈[l2,r2]$中是否有点,离线树状数组即可。

复杂度$\mathcal{O}(n\log n)$。

code:

 #include<bits/stdc++.h>
#include "werewolf.h"
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define per(i,x,y) for (int i=(x);i>=(y);i--)
#define ll long long
#define VI vector<int>
using namespace std;
const int N=2e5+;
int u,v,n,m,Q,top,bit[N]; VI ans,G[N];
struct node{
int x,y,ty,op,id;
node(){}
node(int x,int y,int ty,int op,int id):x(x),y(y),ty(ty),op(op),id(id){}
}q[N*];
bool cmp(node x,node y){ return x.x<y.x||x.x==y.x&&x.ty<y.ty; }
struct Kruskal_rebuild_tree{
int cnt,head[N],fa[N],clk,in[N],out[N],f[N][];
struct edge{ int to,nxt; }e[N];
void adde(int x,int y){ e[++cnt].to=y; e[cnt].nxt=head[x]; head[x]=cnt; }
int getfa(int x){ return x==fa[x]?x:fa[x]=getfa(fa[x]); }
void dfs(int u,int ty){
rep (i,,) f[u][i]=f[f[u][i-]][i-];
in[u]=++clk;
for (int i=head[u];i;i=e[i].nxt) f[e[i].to][]=u,dfs(e[i].to,ty);
out[u]=clk;
}
void build(int ty){
cnt=; rep (x,,n) fa[x]=x,head[x]=;
if (!ty){
per (x,n,)
for (auto y:G[x])
if (x<y&&getfa(x)!=(y=getfa(y))) adde(x,y),fa[y]=x;
} else{
rep (x,,n)
for (auto y:G[x])
if (x>y&&getfa(x)!=(y=getfa(y))) adde(x,y),fa[y]=x;
}
rep (i,,n) if (getfa(i)==i) dfs(i,ty);
}
int qry(int x,int lim,int ty){
per (i,,)
if (f[x][i]&&(!ty?f[x][i]>=lim:f[x][i]<=lim)) x=f[x][i];
return x;
}
}T[];
void add(int x){ for (;x<=n;x+=x&-x) bit[x]++; }
int qry(int x){ int s=; for (;x;x-=x&-x) s+=bit[x]; return s; }
VI check_validity(int _n,VI x,VI y,VI s,VI t,VI l,VI r){
n=_n; m=x.size(),Q=s.size();
rep (i,,m-) G[++x[i]].push_back(++y[i]),G[y[i]].push_back(x[i]);
T[].build(); T[].build();
rep (i,,n) q[++top]=node(T[].in[i],T[].in[i],,,);
rep (i,,Q-){
++s[i],++t[i],++l[i],++r[i];
int u=T[].qry(s[i],l[i],),v=T[].qry(t[i],r[i],);
int l1=T[].in[u],r1=T[].out[u],l2=T[].in[v],r2=T[].out[v];
q[++top]=node(r1,r2,,,i);
if (l1>) q[++top]=node(l1-,r2,,-,i);
if (l2>) q[++top]=node(r1,l2-,,-,i);
if (l1>&&l2>) q[++top]=node(l1-,l2-,,,i);
}
sort(q+,q++top,cmp); ans.resize(Q);
rep (i,,top)
if (!q[i].ty) add(q[i].y); else ans[q[i].id]+=qry(q[i].y)*q[i].op;
rep (i,,Q-) ans[i]=!!ans[i];
return ans;
}

uoj407 【IOI2018】狼人的更多相关文章

  1. [IOI2018]狼人

    [IOI2018]狼人 luogu UOJ 对人形和狼形分别建克鲁斯卡尔重构树 每次询问就是对于两棵树dfs序的一个二维数点,主席树维护 #include<bits/stdc++.h> u ...

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

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

  3. [IOI2018]狼人——kruskal重构树+可持久化线段树

    题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...

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

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

  5. ghj1222被坑记录[不持续更新]

    考试注意事项:link1 link2 (密码:wangle) 调不出来bug,可以先透彻一会儿或者是上个厕所或者坐一会别的题(间隔至少20min),然后通读代码 -1. 考试先读题,读题之后搞出一个做 ...

  6. [note]克鲁斯卡尔重构树

    克鲁斯卡尔重构树 又叫并查集重构树 大概在NOI2018之前还是黑科技 现在?烂大街了 主要是针对图上的对边有限制的一类问题 比如每次询问一个点u不能经过边权大于w的边能走到的第k大点权是多少 也就是 ...

  7. NOIWC2019游记

    更新完了? ghj1222这个智障因为NOIP考的太菜没有去THUWC和PKUWC,但是NOIWC还是苟进去了 由于已经结束了,好多事实忘了,所以可能不完整 2019/1/23 Wednesday 明 ...

  8. [IOI2018] werewolf 狼人

    [IOI2018] werewolf 狼人 IOI2018题解 (其实原题强制在线,要用主席树) 代码: 注意: 1.下标从0~n-1 2.kruskal重构树开始有n个节点,tot从n开始,++to ...

  9. [IOI2018] werewolf 狼人 kruskal重构树,主席树

    [IOI2018] werewolf 狼人 LG传送门 kruskal重构树好题. 日常安利博客文章 这题需要搞两棵重构树出来,这两棵重构树和我们平时见过的重构树有点不同(据说叫做点权重构树?),根据 ...

随机推荐

  1. Dream------Hadoop--FSDataInputStream和FSDataOutputStream

    一.FSDataInputStream    FileSystem中的open()方法实际上返回的是一个FSDataInputStream,而不是标准的java.io类.这个类是java.io.Dat ...

  2. Css中实现一个盒子固定宽度,另一个盒子宽度自适应的方法

    Css中实现一个盒子固定宽度,另一个盒子宽度自适应的方法 网上方法很多,个人认为以下两种思想是最为常用的. 一种是让第一个盒子脱离文档流,第二个盒子离左边有一定距离. 第二种方法是使用flex布局,不 ...

  3. 编译安装 zbar 时两次 make 带来的惊喜

    为了装 php 的条形码扩展模块 php-zbarcode,先装了一天的 ImageMagick 和 zbar.也许和我装的 Ubuntu 17.10 的有版本兼容问题吧,总之什么毛病都有,apt 不 ...

  4. ajax.BeginForm异步提交表单并显示更新数据

    view代码: <!--基本信息模块--> 2 <div class="profile_box" id="basicInfo"> 3 & ...

  5. mysql高可用架构 -> MHA简介-01

    作者简介 松信嘉範:MySQL/Linux专家2001年索尼公司入职2001年开始使用oracle2004年开始使用MySQL2006年9月-2010年8月MySQL从事顾问2010年-2012年 D ...

  6. js实现table导出Excel,保留table样式

    浏览器环境:谷歌浏览器 1.在导出Excel的时候,保存table的样式,有2种方法,①是在table的行内写style样式,②是在模板里面添加样式 2.第一种方式:行内添加样式 <td sty ...

  7. SQLAlchemy-对象关系教程ORM-连接,子查询

    对象关系教程ORM-连接 一:内连接 方法一: for u, a in session.query(User, Address).\ filter(User.id==Address.user_id). ...

  8. 统计学习方法九:EM算法

    一.EM算法是什么? EM算法是一种迭代算法,用于含有隐变量的概率模型参数的极大似然估计. 作用:简单直白的说,估计参数 是一种生成模型 (1)用在概率模型中 (2)含有隐变量 (3)用极大似然估计方 ...

  9. python dict交换key value值

    方法一: 使用dict.items()方式 dict_ori = {'A':1, 'B':2, 'C':3} dict_new = {value:key for key,value in dict_o ...

  10. KMP模板及总结

    KMP是一种字符串匹配算法,它在时间复杂度上较暴力匹配算法由很大的优势.比如我要找字符串S中是否存在子串P,如果暴力匹配的话,则时间复杂度为O(n*m),而kmp算法时间复杂度为O(n+m). 这里我 ...