首页 > 其他分享 >CF319E-Ping-Pong【线段树】

CF319E-Ping-Pong【线段树】

时间:2024-08-01 20:09:31浏览次数:6  
标签:return val int CF319E Ping mid flag 区间 Pong

正题

题目链接:https://www.luogu.com.cn/problem/CF319E


题目大意

定义一个区间 \((a,b)\) 能走到另一个区间 \((c,d)\) 当 \(c<a<d,c<b<d\) 。

你有两个操作

  1. 往集合中加入一个区间 \((a,b)\) ,保证加入的区间长度单调递增。
  2. 询问一个区间能否走到另一个区间。

\(1\leq n\leq 10^5,1\leq a\leq b\leq 10^9\)


解题思路

我们考虑假设我们从一个区间 \(x\) 能走到区间 \(y\) ,区间 \(y\) 能走到区间 \(z\) ,那么区间 \(x\) 肯定能走到区间 \(z\) 。也就是对于单向边我们只会走一次,分析一下性质,如果我们知道区间 \(b\) 所在的边双连通分量范围 \([L,R]\) ,那么区间 \(a\) 能走到区间 \(b\) 的充要条件是区间 \(a\) 是 \([L,R]\) 的一个严格子区间。

那么现在问题就变为了动态维护这些区间的边双了,因为保证了加入的区间长度单调递增,所以我们不需要考虑新加入的区间被包含的可能,所以如果新加入的区间与某个边双的范围区间 \([L,R]\) 是双向的,这个区间又不会被这个边双包含,所以这个区间肯定能并入这个边双里。

我们用线段树维护对于每个以 \(x\) 位置为左端点的边双,右端点的最大值,这样就可以暴力每次从线段树中取出一个边双看与新区间是否连通,使用并查集合并即可。

时间复杂度:\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=2e5+10;
int n,m,cnt,op[N],x[N],y[N],b[N],fa[N],pos[N],l[N],r[N];
pair<int,int> w[N<<2];
set<pair<int,int> >v[N];
void Change(int x,int L,int R,int pos,pair<int,int> val){
	if(L==R){
		w[x]=max(w[x],val);
		v[L].insert(val);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid)Change(x*2,L,mid,pos,val);
	else Change(x*2+1,mid+1,R,pos,val);
	w[x]=max(w[x*2],w[x*2+1]);
	return;
}
bool Del(int x,int L,int R,int l,int r,pair<int,int> val){
	if(l>r)return 0;
	if(L==R){
		if(w[x]!=val)return 0;
		v[L].erase(val);
		if(v[L].size())w[x]=*v[L].rbegin();
		else w[x]=mp(0,0);
		return 1;
	}
	int mid=(L+R)>>1,flag=0;
	if(L==l&&R==r){
		if(w[x]!=val)flag=0;
		else if(w[x*2]==val)flag=Del(x*2,L,mid,l,mid,val);
		else flag=Del(x*2+1,mid+1,R,mid+1,r,val);
	}
	else{
		if(r<=mid)flag=Del(x*2,L,mid,l,r,val);
		else if(l>mid)flag=Del(x*2+1,mid+1,R,l,r,val);
		else{
			bool flag=Del(x*2,L,mid,l,mid,val);
			if(!flag)flag=Del(x*2+1,mid+1,R,mid+1,r,val);
		}
	}
	w[x]=max(w[x*2],w[x*2+1]);
	return flag;
}
pair<int,int> Ask(int x,int L,int R,int l,int r){
	if(l>r)return mp(0,0);
	if(L==l&&R==r)return w[x];
	int mid=(L+R)>>1;
	if(r<=mid)return Ask(x*2,L,mid,l,r);
	if(l>mid)return Ask(x*2+1,mid+1,R,l,r);
	return max(Ask(x*2,L,mid,l,mid),Ask(x*2+1,mid+1,R,mid+1,r));
}
int find(int x)
{return (fa[x]==x)?(x):(fa[x]=find(fa[x]));}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&op[i],&x[i],&y[i]);
		if(op[i]==1){
			b[++m]=x[i];
			b[++m]=y[i];
		}
	}
	for(int i=1;i<=n;i++)fa[i]=i;
	sort(b+1,b+1+m);
	m=unique(b+1,b+1+m)-b-1;
	for(int i=1;i<=n;i++){
		if(op[i]==1){
			cnt++;pos[cnt]=i;
			x[i]=lower_bound(b+1,b+1+m,x[i])-b;
			y[i]=lower_bound(b+1,b+1+m,y[i])-b;
			l[cnt]=x[i];r[cnt]=y[i];
			while(true){
				pair<int,int> son=Ask(1,1,m,x[i],y[i]-1);
				if(son.first<=y[i])break;
				int z=son.second;
				Del(1,1,m,x[i],y[i]-1,son);
				if(fa[z]!=z)continue;
				fa[z]=cnt;
				l[cnt]=min(l[cnt],l[z]);
				r[cnt]=max(r[cnt],r[z]);
			}
			while(true){
				pair<int,int> son=Ask(1,1,m,1,x[i]-1);
				if(son.first<=x[i])break;
				int z=son.second;
				Del(1,1,m,1,x[i],son);
				if(fa[z]!=z)continue;
				fa[z]=cnt;
				l[cnt]=min(l[cnt],l[z]);
				r[cnt]=max(r[cnt],r[z]);
			}
			Change(1,1,m,l[cnt],mp(r[cnt],cnt));
		}else{
			if(find(x[i])==find(y[i]))puts("YES");
			else{
				x[i]=pos[x[i]];y[i]=find(y[i]);
				if(x[x[i]]>=l[y[i]]&&y[x[i]]<=r[y[i]]&&!(x[x[i]]==l[y[i]]&&y[x[i]]==r[y[i]]))
					puts("YES");
				else puts("NO");
			}
		}
	}
	return 0;
}

标签:return,val,int,CF319E,Ping,mid,flag,区间,Pong
From: https://www.cnblogs.com/QuantAsk/p/18337386

相关文章

  • New-SmbMapping命令在PowerShell中用于创建新的SMB映射,其主要参数如下:
    New-SmbMapping命令在PowerShell中用于创建新的SMB映射,其主要参数如下:RemotePath:指定远程共享的路径。可以是网络共享的UNC路径,如\\server\share。LocalPath:指定本地计算机上的映射路径,通常是一个驱动器号或者文件夹路径。例如,Z:或C:\Share。Credential:用于连接远程共......
  • 使用 DQN 实现 pong,使用 python 中的特征向量而不是像素。我的 DQNA 实现代码正确吗,因
    我正在致力于使用OpenAI的Gym为Pong游戏实现强化学习(RL)环境。目标是训练人工智能代理通过控制球拍来打乒乓球。代理收到太多负面奖励,即使它看起来移动正确。具体来说,奖励函数会惩罚远离球的智能体,但这种情况发生得太频繁,即使球朝球拍移动时似乎也会发生。观察......
  • SPONGE常用教程0:软件安装教程
    课程准备阶段,介绍最简明安装流程,安装过程中如果遇到其他问题,请移步官方教程。第三方软件只提供个人安装心得。软件安装环境默认为linux。软件支持SPONGE(SimulationPackagetOwardNextGEnerationmolecularmodelling)是由北京大学高毅勤课题组开发的分子动力学模拟程序。XPO......
  • “ModuleNotFoundError:没有名为‘numpy.typing’的模块”
    我正在尝试导入ArrayLikedoingfromnumpy.typingimportArrayLike,并且收到标题中提到的错误:ModuleNotFoundError:Nomodulenamed'numpy.typing'我知道我可以简单地编写importnumpy.typingasnpt如文档所示,但我想要简单性只是导入......
  • 广域网(WAN)、局域网(LAN)的区别与联系、WLAN与WiFi的关系,ipconfig和ping
    1.广域网和局域网广域网(WideAreaNetwork),简称WAN,是一种地域范围覆盖广的计算机网络的集合,通常所覆盖的范围从几十公里到几千公里,它能连接多个地区、城市和国家。由于其超长的覆盖范围,发送介质主要是政府或者大型企业部署的电话线或光纤,因此又被大家亲切的称为:外网、公网。......
  • Pythonanywhere - ping:套接字:不允许操作
    请帮忙。我有一个Telegram机器人,当我从Bash控制台启动他时,它每60秒ping一次静态IP-它工作正常,但每天停止工作一次。我尝试使用“始终开启任务”,但在日志文件中收到“ping:套接字:不允许操作”。我有5美元帐户,我能做什么?从Bash控制台运行时我看到的内容:---17......
  • SPONGE常用教程:蛋白+配体模拟2
    前序课程目录应用场景简述;-[Done]DSDP:蛋白-配体对接;-[Done]XPONGE:蛋白-配体建模,加溶剂;-[Done]SPONGE:能量极小化-NVT-NPT-正式模拟;XPONGE:数据简单后处理。4.SPONGE:能量极小化-NVT-NPT-正式模拟文件下载进入建模文件目录,如下图:SPONGE输入文件采用独特的参......
  • Linux Kernel Utilization Clamping简介
    随着linux内核调度技术的不断演进,目前存在多个调度类(stop、deadline、rt、cfs、idle)以满足不同性质和要求的任务(task)的调度需求。对于用户空间来说,完全公平调度器(CFS)和实时调度器(RT)是绝大多数任务所使用的,但是基于POSIXPriority算法不足以支撑关于选核和调频的调度器特性。关于任......
  • SPONGE常用教程:蛋白+配体模拟1
    软件支持SPONGE(SimulationPackagetOwardNextGEnerationmolecularmodelling)是由北京大学高毅勤课题组开发的分子动力学模拟程序。安装教程XPONGE使用python编写的分子动力学模拟前后处理工具。简易安装:pipinstallgit+https://gitee.com/gao_hyp_xyj_admin/xponge.gitDS......
  • Android Spingboot 实现SSE通信案例
    SSESSE(Server-SentEvents)是一种用于实现服务器主动向客户端推送数据的技术,它基于HTTP协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。Server-SentEvents(SSE)和Sockets都可以用于实现服务器向客户端推......