【BZOJ5005】乒乓游戏 [线段树][并查集]
乒乓游戏
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】乒乓游戏 [线段树][并查集]的更多相关文章
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)
2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- 【XSY2707】snow 线段树 并查集
题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...
- bzoj 2054: 疯狂的馒头(线段树||并查集)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...
- 【CF687D】Dividing Kingdom II 线段树+并查集
[CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...
- 【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集
[BZOJ1453][Wc]Dface双面棋盘 Description Input Output Sample Input Sample Output HINT 题解:话说看到题的第一反应其实是LCT ...
- codeforces 811E Vladik and Entertaining Flags(线段树+并查集)
codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...
- 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]
Vladik and Entertaining Flags Time Limit: 20 Sec Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...
随机推荐
- 解析HTML利器AngleSharp介绍
解析HTML利器AngleSharp介绍 AngleSharp是基于.NET(C#)开发的专门为解析xHTML源码的DLL组件. 项目地址:https://github.com/FlorianRapp ...
- android中activity,window,view之间的关系
activity:控制单元 window:承载模型 view:显示视图 几个小tip: 1.一个 Activity 构造的时候一定会构造一个 Window(PhoneWindow),并且只有一个 2. ...
- Qt 实现脉搏检测-2,简陋的功能产品
今天终于可以接上硬件来显示真是的脉搏情况了,上图 主要就是显示脉搏的心跳曲线,和IBI 数据来源是三个,串口,网口和蓝牙,目前只实现了串口,过程应该都是差不多的,监听,读取,解析,等硬件更新后,再次更 ...
- Django2.1.3框架中(fields.E300)和(fields.E307)报错处理
使用Django框架创建了Web项目,修改了模型models.py之后,执行数据库迁移操作,出现如下报错: models.py内容如下: from django.db import models fr ...
- Fluentd插件使用方法
这里主要介绍从MongoDB同步数据到ODPS.ruby环境的搭建以及fluent_plugin_mongo_odps插件的安装.1.准备工作1.1安装环境要求Ruby 2.1以上Gem 2.4.5以 ...
- Linux IO乱序
原创翻译,转载请注明出处. 在一些平台,所谓的内存映射I/O在保序执行这方面是没有保障的.在这些平台,驱动写入器负责保证I/O写操作按照预期的顺序写到设备内存映射地址. 代表性的做法是通过读取一个安全 ...
- Linux挂载Win共享文件夹_VmwareTools
- wait_event_interruptible_timeout
最近一套方案涉及到内核线程之间的同步,用到了函数wait_event_interruptible_timeout函数,大致是这样: A:是一个后台的线程,平常没事就睡觉,有时被唤醒,或者每5分钟醒一次 ...
- JSP表单提交出现中文乱码的解决方法
1)post方式 在servlet的doGet( ) doPost( ) 中增加以下代码: response.setContentType("text/html;charset=utf- ...
- JDK的弃儿:Vector、Stack、Hashtable、Enumeration
随着JDK的发展,一些设计缺陷或者性能不足的类库难免会被淘汰,最常见的就是Vector.Stack.HashTable和Enumeration了. Vector(@since 1.0) 首先看看Vec ...