乒乓游戏

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  5
  1 1 5
  1 5 11
  2 1 2
  1 2 9
  2 1 2

Sample Output

  NO
  YES

HINT

  

Main idea

  如果一个区间的端点在区间内,则这个区间可以走到那个区间,询问一个区间能否到另一个区间。

Source

  首先我们立马想到了:如果两个区间严格有交集,那么这两个区间所能到达的区间集合是一样的。那么如果两个区间严格有交集的话我们就可以把它们合并起来,这里运用并查集。

  这样处理完之后,剩下的区间只有两种情况:包含或者相离。那么查询的时候显然只要判断两个区间指向的大区间的情况即可。

  我们要怎么合并呢?显然就是在线段树上进行操作,对于线段树上的每个节点开个vector,存下严格包含这个节点表示的[l,r]的区间的编号,那么我们加入新区间的时候,只要把左右端点在线段树上往下走,如果遇到这个线段树上的节点上的vector有东西,就记录几个区间的最小左端点以及最大右端点,把这几个区间的父亲都指向这个新区间,再删除掉这几个区间即可。然后合并完之后,把得到的新区间再放到各个点的vector进去。

  最后,由于这题区间端点权比较大,所以要先离散化。

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std; const int ONE=*;
const int INF=1e9+; int n;
int Num,cnt; vector <int> Node[ONE]; struct power
{
int l,r,opt;
}a[ONE],interval[ONE]; int Q[ONE],li_num;
struct LISAN
{
int pos,val;
}Li[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} namespace LI
{
void add(int i)
{
if(a[i].opt!=) return;
Num++;
Li[++li_num].val = a[i].l; Li[li_num].pos = li_num;
Li[++li_num].val = a[i].r; Li[li_num].pos = li_num;
} int cmp(const LISAN &a,const LISAN &b) {return a.val < b.val;}
void Lisan()
{
sort(Li+, Li+li_num+, cmp); cnt=;
Li[].val=-INF;
for(int i=;i<=li_num;i++)
{
if(Li[i].val!=Li[i-].val) ++cnt;
Q[Li[i].pos]=cnt;
}
Num=cnt; cnt=;
for(int i=;i<=n;i++)
if(a[i].opt==)
a[i].l=Q[++cnt], a[i].r=Q[++cnt]; }
} int fat[ONE];
int Find(int x)
{
if(fat[x]==x) return x;
return fat[x]=Find(fat[x]);
} namespace Seg
{
void Delete(int i,int l,int r,int L)
{
if(Node[i].size())
{
for(int j=; j<Node[i].size(); j++)
{
int id=Node[i][j];
fat[ Find(id) ] = cnt;
interval[cnt].l = min(interval[cnt].l, interval[id].l);
interval[cnt].r = max(interval[cnt].r, interval[id].r);
}
Node[i].clear();
}
if(l==r) return;
int mid = (l+r)>>;
if(L <= mid) Delete(i<<, l, mid, L);
else Delete(i<<|, mid+, r, L);
} void Update(int i,int l,int r,int L,int R)
{
if(L>R) return;
if(L<=l && r<=R)
{
Node[i].push_back(cnt);
return;
}
int mid=(l+r)>>;
if(L<=mid) Update(i<<,l,mid,L,R);
if(mid+<=R) Update(i<<|,mid+,r,L,R);
}
} bool P_edge(power a,power b)
{
if( (b.l<a.l && a.l<b.r) || (b.l<a.r && a.r<b.r)) return ;
return ;
} int main()
{
n=get();
for(int i=;i<=n;i++)
{
a[i].opt=get();
a[i].l=get(); a[i].r=get();
LI::add(i);
}
for(int i=;i<=Num;i++) fat[i]=i; LI::Lisan(); cnt=;
for(int i=;i<=n;i++)
{
if(a[i].opt==)
{
interval[++cnt] = a[i];
Seg::Delete(,,Num, a[i].l);
Seg::Delete(,,Num, a[i].r);
Seg::Update(,,Num, interval[cnt].l+,interval[cnt].r-);
}
else
{
int x=Find(a[i].l), y=Find(a[i].r);
if(x==y || P_edge(interval[x] , interval[y]))
printf("YES\n");
else
printf("NO\n");
}
}
}

【BZOJ5005】乒乓游戏 [线段树][并查集]的更多相关文章

  1. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  2. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  3. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  4. 【XSY2707】snow 线段树 并查集

    题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...

  5. bzoj 2054: 疯狂的馒头(线段树||并查集)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...

  6. 【CF687D】Dividing Kingdom II 线段树+并查集

    [CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...

  7. 【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集

    [BZOJ1453][Wc]Dface双面棋盘 Description Input Output Sample Input Sample Output HINT 题解:话说看到题的第一反应其实是LCT ...

  8. codeforces 811E Vladik and Entertaining Flags(线段树+并查集)

    codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...

  9. 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]

    Vladik and Entertaining Flags Time Limit: 20 Sec  Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...

随机推荐

  1. 面试官常问的10个Linux问题

    1.如何暂停一个正在运行的进程,把其放在后台(不运行)? 为了停止正在运行的进程,让其再后台运行,我们可以使用组合键Ctrl+Z. 2.什么是安装Linux所需的最小分区数量,以及如何查看系统启动信息 ...

  2. abo dto属性验证的坑

    问题回现: public class ShipmentRequestDto { public string FromPhoneNumber { get; set; } /// <summary& ...

  3. Ubuntu 安装Qt

    下载Qt,这里步骤略过 设置共享, 如果设置共享没有问题,可以不看下面的 如果设置共享,在Ubuntu中找不到共享文件的话,那安找下面的步骤在来一次. http://blog.csdn.net/z60 ...

  4. 阿里云ECS下基于Centos7.4安装MySQL5.7.20

     1.首先登录阿里云ECS服务器,如下图所示: 2.卸载MariaDB 说明:CentOS7.x默认安装MariaDB而不是MySQL,而且yum服务器上也移除了MySQL相关的软件包.因为Maria ...

  5. tensorflow Importing Data

    tf.data API可以建立复杂的输入管道.它可以从分布式文件系统中汇总数据,对每个图像数据施加随机扰动,随机选择图像组成一个批次训练.一个文本模型的管道可能涉及提取原始文本数据的符号,使用查询表将 ...

  6. kaldi常用文件查看指令

    目录 1. ark特征文件 2. FST文件 3. mdl模型文件 4. 决策树文件 5. ali.gz对齐文件 资料来自kaldi官方文档. 转载注明出处. 1. ark特征文件 copy-feat ...

  7. android仿QQ的SlideMenu

    这其实很简单就可以实现,只需要自定义一个View继承自HorizontalScrollView 1,新建一个项目,再新建一个MySlideMenu继承HorizontalScrollView publ ...

  8. android命令模式IntentService 远程下载文件

    服务可用在一下情景: 1,用户离开activity后,仍需要继续工作,例如从网络下载文件,播放音乐. 2,无论activity出现或离开,都需要持续工作,例如网络聊天应用. 3,连接网络服务,正在使用 ...

  9. select2赋值需要注意

    $('#mySelect2').val(data.id).trigger('change'); 需要在赋值后,调用下change事件,不然的话展示值的span不会显示select最新的选中值.

  10. 《学习OpenCV》课后习题解答8

    题目:(P126) 本章完整讲述了基本的输入/输出编程以及OpenCV的数据结构.下面的练习是基于前面的知识做一些应用,为后面大程序的实现提供帮助. a.创建一个程序实现以下功能:(1)从视频文件中读 ...