Luogu4899 IOI2018狼人(kruskal重构树+主席树)
可以发现询问的即是“由起点开始‘只经过编号大于等于l的点’所形成的连通块”与“由终点开始‘只经过编号小于等于r的点’所形成的连通块”是否有交集。于是建出重构树,就可以知道每个询问的连通情况了。现在要知道的是两个连通块的交集,考虑每个点是否有可能在里面。于是按照两棵重构树的dfs序给每个点一个二维坐标,问题就变为二维数点了,主席树即可。
注意编号从0开始。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 200010
#define M 400010
int n,m,q,root[N<<],cnt;
struct data{int x,y;
}e[M];
struct data2{int l,r,x;
}tree[N<<];
bool cmp(const data&a,const data&b)
{
return a.y<b.y;
}
struct kruskal_tree
{
int t,p[N<<],cnt,tot,fa[N<<],value[N<<],dfn[N<<],size[N<<],f[N<<][];
struct data{int to,nxt;}edge[M<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int k)
{
dfn[k]=++tot;
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
{
f[edge[i].to][]=k;
dfs(edge[i].to);
size[k]+=size[edge[i].to];
}
}
int geta(int x,int k)
{
for (int j=;~j;j--) if (value[f[x][j]]>=k) x=f[x][j];
return x;
}
int getb(int x,int k)
{
for (int j=;~j;j--) if (value[f[x][j]]<=k) x=f[x][j];
return x;
}
void make()
{
for (int i=;i<=n;i++) fa[i]=i,value[i]=i;cnt=n;
for (int i=;i<=m;i++)
if (find(e[i].x)!=find(e[i].y))
{
int u=find(e[i].x),v=find(e[i].y);
cnt++;fa[u]=fa[v]=fa[cnt]=cnt;
addedge(cnt,u),addedge(cnt,v);
value[cnt]=e[i].y;
}
dfs(cnt);
f[cnt][]=cnt;
for (int j=;j<;j++)
for (int i=;i<=cnt;i++)
f[i][j]=f[f[i][j-]][j-];
}
}a,b;
void ins(int &k,int l,int r,int x)
{
tree[++cnt]=tree[k],k=cnt;tree[k].x++;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(tree[k].l,l,mid,x);
else ins(tree[k].r,mid+,r,x);
}
int query(int x,int y,int l,int r,int p,int q)
{
if (!x) return ;
if (l==p&&r==q) return tree[x].x>tree[y].x;
int mid=l+r>>;
if (q<=mid) return query(tree[x].l,tree[y].l,l,mid,p,q);
else if (p>mid) return query(tree[x].r,tree[y].r,mid+,r,p,q);
else return query(tree[x].l,tree[y].l,l,mid,p,mid)|query(tree[x].r,tree[y].r,mid+,r,mid+,q);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("wolf.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),q=read();
for (int i=;i<=m;i++)
{
e[i].x=read()+,e[i].y=read()+;
if (e[i].x>e[i].y) swap(e[i].x,e[i].y);
}
sort(e+,e+m+,cmp);
b.make();
for (int i=;i<=m;i++) swap(e[i].x,e[i].y);
sort(e+,e+m+,cmp);reverse(e+,e+m+);
a.make();
for (int i=;i<=n;i++) e[i].x=b.dfn[i],e[i].y=a.dfn[i];
sort(e+,e+n+,cmp);
for (int i=;i<=n;i++)
{
for (int j=e[i-].y+;j<=e[i].y;j++) root[j]=root[j-];
ins(root[e[i].y],,b.cnt,e[i].x);
}
for (int i=e[n].y+;i<=a.cnt;i++) root[i]=root[i-];
while (q--)
{
int x=read()+,y=read()+,l=read()+,r=read()+;
int u=a.geta(x,l),v=b.getb(y,r);
printf("%d\n",query(root[a.dfn[u]+a.size[u]-],root[a.dfn[u]-],,b.cnt,b.dfn[v],b.dfn[v]+b.size[v]-));
}
return ;
}
Luogu4899 IOI2018狼人(kruskal重构树+主席树)的更多相关文章
- LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...
- [IOI2018] werewolf 狼人 [kruskal重构树+主席树]
题意: 当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点) 当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点) 然后问题转化成人形和狼形能到的点 ...
- luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)
题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...
- UOJ#407. 【IOI2018】狼人 Kruskal,kruskal重构树,主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ407.html 题解 套路啊. 先按照两个节点顺序各搞一个kruskal重构树,然后问题转化成两棵krus ...
- [IOI2018]狼人——kruskal重构树+可持久化线段树
题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...
- 【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][ ...
随机推荐
- program files与program files(x86)的区别
简单来说:Program Files (x86)存放了一些32位的系统文件.它和正常的Program Files以及Windows文件夹一样,都属于系统文件夹,请勿随意改动. 64位Windows中提 ...
- 第四篇 与Flask相关的插件(flask-session、wtforms)
公司中使用SQL的种方式: 1. 写Django:ORM(关系对象映射), 2. 写Flask和其他:有两种方式: (1) 原生SQL:使用原生SQL有两种选择: A. pymysql (python ...
- Fiddler - 拦截手机请求
1. 在电脑上安装Fillder. 安装好之后的Fiddler 打开是这样的: 2. 浏览器访问http://127.0.0.1:8888/fiddler,下载证书并安装 3. 打开抓取https请求 ...
- Redis命令续
Redis 集合命令 下表列出了 Redis 集合基本命令: 序号 命令及描述 1 SADD key member1 [member2] 向集合添加一个或多个成员 2 SCARD key 获取集合的 ...
- 孤荷凌寒自学python第八十天开始写Python的第一个爬虫10
孤荷凌寒自学python第八十天开始写Python的第一个爬虫10 (完整学习过程屏幕记录视频地址在文末) 原计划今天应当可以解决读取所有页的目录并转而取出所有新闻的功能,不过由于学习时间不够,只是进 ...
- 文件上传:CommonsMultipartResolver
一. 简介 CommonsMultipartResolver是基于Apache的Commons FileUpload来实现文件上传功能的,主要作用是配置文件上传的一些属性. 二. 配置 1)依赖Apa ...
- 理解glance
摘要: 本节介绍 OpenStack Image 服务 Glance 的基本概念. OpenStack 由 Glance 提供 Image 服务. 理解 Image 要理解 Image Service ...
- qt qchart缩放后坐标轴间隔取整
使用qt的qchart显示数据曲线,坐标轴QValueAxis可以设置刻度间隔数量,但每个刻度的数值是根据坐标的极值除以间隔数量得到的,不一定是整数,导致曲线控件的显示刻度不适合观察. 如图: 纵坐标 ...
- Pandas dataframe数据写入文件和数据库
转自:http://www.dcharm.com/?p=584 Pandas是Python下一个开源数据分析的库,它提供的数据结构DataFrame极大的简化了数据分析过程中一些繁琐操作,DataFr ...
- 编译安装hadoop2.6.3
一.安装环境 1.1 JAVA 安装java1.7 下载jdk1.7: [root@node1~]# wget http://download.oracle.com/otn-pub/java/jd ...