题意:nnn个点mmm条边的无向图,qqq次询问,每次给定s,t,L,Rs,t,L,Rs,t,L,R,判断是否存在一条sss到ttt的路径,使得路径上可以找到一点kkk,满足此路径s∼ks\sim ks∼k的部分标号都≥L\geq L≥L且k∼tk\sim tk∼t标号都≤R\leq R≤R(均包括端点)

n,q≤2×105,m≤4×105n,q\leq2\times10^5,m\leq4\times10^5n,q≤2×105,m≤4×105

显然找到sss只走≥L\geq L≥L的点能到达的点集SSS,ttt只走≤R\leq R≤R能到达TTT,判断SSS和TTT是否有交即可

分别从大到小和从小到大建出Kruscal重构树,发现SSS和TTT是树上的一个子树

什么?只有点权怎么建Kruscal重构树?

因为你走一条边实际上受到了两个端点的限制,所以直接取两个点的min⁡/max⁡\min/\maxmin/max当边权就可以了

然后对SSS和TTT跑dfs序,设两个dfs序数组分别为dfsa,dfsbdfsa,dfsbdfsa,dfsb

那么对于uuu点可以映射成平面上的(dfsau,dfsbu)(dfsa_u,dfsb_u)(dfsau​,dfsbu​)

二维数点即可

因为横纵坐标分别互不相同,所以写主席树会很清真

注意建Kruscal重构树的虚点不要加到主席树里面,否则会出奇怪的问题

复杂度O(nlog⁡n)O(n\log n)O(nlogn)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 600005
using namespace std;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
struct edge{int u,v;}e[MAXN];
int n,m,q;
inline bool cmp1(const edge& a,const edge& b){return max(a.u,a.v)<max(b.u,b.v);}
inline bool cmp2(const edge& a,const edge& b){return min(a.u,a.v)>min(b.u,b.v);}
inline int Min(const int& x,const int& y){return x<y? x:y;}
inline int Max(const int& x,const int& y){return x>y? x:y;}
struct KruscalRestructTree
{int f[MAXN],fa[MAXN][20],ch[MAXN][2],val[MAXN],cnt;int dfn[MAXN],ed[MAXN],pos[MAXN],tim;int find(int x){return f[x]==x? x:f[x]=find(f[x]);}inline void init(){cnt=n;for (int i=1;i<=n;i++) val[i]=i;for (int i=1;i<=n+m;i++) f[i]=i;}inline void insert(int u,int v,int m(const int&,const int&)){u=find(u),v=find(v);if (u==v) return;f[u]=f[v]=fa[u][0]=fa[v][0]=++cnt;ch[cnt][0]=u,ch[cnt][1]=v;val[cnt]=m(val[u],val[v]);}void dfs(int u){if (!u) return;pos[dfn[u]=++tim]=u;for (int i=1;i<20;i++) fa[u][i]=fa[fa[u][i-1]][i-1];dfs(ch[u][0]),dfs(ch[u][1]);ed[u]=tim;}inline void query(int u,int& l,int& r,int ql,int qr){if (val[u]<ql||qr<val[u]) return (void)(l=0);for (int i=19;i>=0;i--)if (fa[u][i]&&ql<=val[fa[u][i]]&&val[fa[u][i]]<=qr)u=fa[u][i];l=dfn[u],r=ed[u];}
}S,T;
int ch[MAXN<<5][2],sum[MAXN<<5],cnt;
int rt[MAXN];
void insert(int& x,int y,int l,int r,int k)
{x=++cnt;ch[x][0]=ch[y][0],ch[x][1]=ch[y][1],sum[x]=sum[y]+1;if (l==r) return;int mid=(l+r)>>1;if (k<=mid) insert(ch[x][0],ch[y][0],l,mid,k);else insert(ch[x][1],ch[y][1],mid+1,r,k);
}
int query(int x,int l,int r,int ql,int qr)
{if (ql<=l&&r<=qr) return sum[x];if (qr<l||r<ql) return 0;int mid=(l+r)>>1;return query(ch[x][0],l,mid,ql,qr)+query(ch[x][1],mid+1,r,ql,qr);
}
int main()
{n=read(),m=read(),q=read();S.init(),T.init();for (int i=1;i<=m;i++) e[i].u=read()+1,e[i].v=read()+1;sort(e+1,e+m+1,cmp2);for (int i=1;i<=m;i++) S.insert(e[i].u,e[i].v,Min);sort(e+1,e+m+1,cmp1);for (int i=1;i<=m;i++) T.insert(e[i].u,e[i].v,Max);int tot=S.cnt;S.dfs(tot),T.dfs(tot);for (int i=1;i<=tot;i++) if (S.pos[i]<=n) insert(rt[i],rt[i-1],1,tot,T.dfn[S.pos[i]]);else rt[i]=rt[i-1];while (q--){int s,t,l,r;s=read()+1,t=read()+1,l=read()+1,r=read()+1;int lx,rx,ly,ry;S.query(s,lx,rx,l,tot),T.query(t,ly,ry,1,r);if (!lx||!ly){puts("0");continue;}int ans=query(rt[rx],1,tot,ly,ry)-query(rt[lx-1],1,tot,ly,ry);printf("%d\n",!!ans);}return 0;
}

【IOI2018】狼人【Kruscal重构树】【主席树】相关推荐

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

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

  2. 牛客 - 牛半仙的妹子图(并查集+bitset/克鲁斯卡尔重构树+主席树)

    题目链接:点击查看 题目大意:给出一个由 n 个点和 m 条边组成的连通图,每个点都有一种颜色,每条边都有一个权值,现在规定一个起点 st,再给出 q 次询问,每次询问给出区间 [ l , r ] , ...

  3. P4899-[IOI2018]werewolf 狼人【Kruskal重构树,主席树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4899 题目大意 nnn个点的一张无向图,每次询问(s,t,l,r)(s,t,l,r)(s,t,l,r)表示询问能 ...

  4. #3551. [ONTAK2010]Peaks加强版(kruskal 重构树 + 主席树)

    #3551. [ONTAK2010]Peaks加强版 我们要求从一个点出发经过困难值小于等于xxx的路径所能到达的山峰中第kkk高的是什么. 考虑按照边权升序,建议kruskalkruskalkrus ...

  5. Peaks加强版 黑暗爆炸 - 3551 Kruskal重构树 + 主席树

    传送门 文章目录 题意: 思路: 题意: 给你一张图,有nnn个山峰,每个山峰高度为hih_ihi​,有mmm条边,每条边有个难度值wiw_iwi​,现在有qqq个询问,每次询问给定一个山峰vvv,问 ...

  6. [ONTAK2010] Peaks加强版 (kruskal重构树+主席树+倍增)

    Peaks description solution code description 在Bytemountains有N座山峰,每座山峰有他的高度h_i 有些山峰之间有双向道路相连,共M条路径,每条路 ...

  7. P4197-Peaks【Kruskal重构树,主席树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4197 题目大意 nnn个点的一张无向图,每个点有一个hih_ihi​,边有权值. qqq次询问从vvv出发不走权 ...

  8. P4899 [IOI2018] werewolf 狼人(kruskal 重构树 + 主席树)

    P4899 [IOI2018] werewolf 狼人 给定一个有nnn个点mmm条边的无向图,有QQQ个询问 每次输入S,E,L,RS, E, L, RS,E,L,R,表示你在SSS点出发,要到EE ...

  9. 货车运输--kruscal重构树板子

    前置知识: kruscal重构树 用于求解有关两点间路径最大边权最小值和最小边权最大值问题 求解两点间路径最大边权最小值--最大生成树思想,优先选择权值大的边 求解两点间路径最小边权最大值--最小生成 ...

最新文章

  1. Android源码下载资料
  2. 用 C 语言开发一门编程语言 — 变量元素设计
  3. htm tt cite em u
  4. C++Builder函数集(文件操作、获取时间、类型转换等)
  5. 从三个数组中选择满足条件的三个数
  6. jQuery的DOM操作之选择元素
  7. myeclipse去掉js报错
  8. springboot_通过Actuator了解应用程序运行时的内部状况
  9. MAVEN(一)中的Scope
  10. 关于10月16日数据迁移致网友的致歉信
  11. 目录字串最后都不要带目录分隔符
  12. 动手试试Android Studio插件开发
  13. 整合 activiti 7 springcloud
  14. 职业规划报告!草草了事,看看得了
  15. HTML右下角音乐播放器,利用HTML5实现网页底部音乐播放器代码
  16. 北京科技大学计算机实践,北京科技大学计算机实践报告-Excel 练习
  17. Element el-input-number 计数器详解
  18. Linux定时任务的基础操作
  19. Python可视化|matplotlib05-绘图风格大全
  20. JS Array数组和函数

热门文章

  1. 利用tabluea分析数据的案例_利用德温特分析Dartsip的案例检索结果
  2. 收藏 : 50个Excel逆天功能,一秒变“表哥”
  3. 数据这么多,且看R语言怎么处理!
  4. 从概念到案例:初学者须知的十大机器学习算法
  5. mysql字段简索引_MySQL优化看这一篇就够了
  6. python解析xml文件选用模块_python解析xml模块封装代码
  7. java基础代码下载_Java基础(一)(示例代码)
  8. linux nginx mysql php 5.5._搭建基于Linux6.3+Nginx1.2+PHP5+MySQL5.5的Web服务器全过程
  9. php acl rbac,建站常用的用户权限管理模型ACL和RBAC的区别
  10. 机器学习之模型——保存与加载