乒乓游戏

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. 『JavaScript』封装

    封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏.通过封装可以强制实施信息隐藏. 在JavaScript中,并没有显示的声明私有成员的关键字等.所以要想实现封装/信息隐藏就需要从另外的思路出 ...

  2. Qt 建立带有子项目的工程

    刚需,软件需要用到多个子项目 第一步 打开Qt新建子项目工程 如图 在此时鼠标右键,选着新建子项目如图 就是正常的新建项目的步骤,直接上图 完工,可以愉快的撸代码了

  3. 常用模块(数据序列化 json、pickle、shelve)

    本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Py ...

  4. NLP系列-中文分词(基于词典)

    中文分词概述 词是最小的能够独立活动的有意义的语言成分,一般分词是自然语言处理的第一项核心技术.英文中每个句子都将词用空格或标点符号分隔开来,而在中文中很难对词的边界进行界定,难以将词划分出来.在汉语 ...

  5. 感知机学习算法(PLA)

    Perception Learning Algorithm, PLA 1.感知机 感知机是一种线性分类模型,属于判别模型. 感知机模型给出了由输入空间到输出空间的映射: f(X) = sign(WTX ...

  6. kill命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/wangcp-2014/p/5146343.html 1.命令格式: kill[参数][进程号] 2.命令功能: 发送指 ...

  7. c# dll使用注意

    1.dll路径最好不要用到中文,会报:尝试读取或写入受保护的内存.这通常指示其他内存已损坏.

  8. 本周学习总结JAVA

    6. 为如下代码加上异常处理 byte[] content = null; FileInputStream fis = new FileInputStream("testfis.txt&qu ...

  9. 【工作感悟】——xyb项目部署

    [前言] 接手xyb项目维护有一段时间了,除了熟悉业务需求和开发环境外,还没有进行新需求的开发.前几天突然接到一个任务,要去发改委给他们部署一版最新的系统.本来事情也不大,也没有很难.但是本来是大屈. ...

  10. 如何使用 window.open() 处理ajax请求返回的url: 在本页面打开并防止浏览器拦截

    ajax请求中用window.open()打开请求返回url(例如实现下载功能时),可能会因为跨域问题导致浏览器拦截 解决办法是:在请求前,打开一个窗口,请求成功后将返回的url直接赋值给该窗口的hr ...