luogu P3602 Koishi Loves Segments |堆+离散化贪心

题目描述

Koishi喜欢线段。

她的\(n\)条线段都能表示成数轴上的某个闭区间\([l,r]\)。Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了。

Flandre看她和线段玩得很起开心,就抛给她一个问题:

数轴上有\(m\)个点突然兴奋,如果自己被身上覆盖了超过\(x\)条线段,这个点就会浑身难受然后把Koishi批判一番。

Koishi十分善良,为了不让数轴上的点浑身难受,也为了让自己开心,她想在数轴上放入尽量多的线段。

按照套路,Koishi假装自己并不会做这道题,所以她就来求你帮忙。并承诺如果你解决了问题就给你打一通电话w。

输入格式

第一行两个个整数n,mn,mn,m,分别表示插入的线段数和关键点数。

接下来\(n\)行,每行两个整数\(l,r(l\leq r)\),表示线段\([l,r]\)的端点。

接下来\(m\)行,每行两个整数\(p,x\),表示有个位于ppp的点突然兴奋,并认为自己身上不得覆盖超过\(x\)条线段

输出格式

一个整数,表示最多能放入的线段数

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=8e5+5;
#define int long long
int b[N],num,n,m;
#define lb lower_bound
int e[N],P[N],X[N];
struct mzx{
	int l,r;
}a[N];
inline bool nmp(mzx a,mzx b){
	return a.l<b.l;
}
priority_queue<int>Q;
int vis[N];
signed main(){
	cin>>n>>m;
	for(int i=1,l,r;i<=n;i++){
		scanf("%lld%lld",&l,&r);
		b[++num]=l,b[++num]=r;
		a[i]=(mzx){l,r};
	}
	for(int i=1;i<=m;i++){
		scanf("%lld%lld",&P[i],&X[i]);
		b[++num]=P[i];
	}
	sort(b+1,b+1+num);
	int len=unique(b+1,b+1+num)-b-1;
	for(int i=1;i<=n;i++){
		a[i].l=lb(b+1,b+1+len,a[i].l)-b;
		a[i].r=lb(b+1,b+1+len,a[i].r)-b;
	}
	sort(a+1,a+1+n,nmp);
	for(int i=1;i<=len;i++)e[i]=2e9;
	for(int i=1;i<=m;i++){
		P[i]=lb(b+1,b+1+len,P[i])-b;
		e[P[i]]=min(e[P[i]],X[i]);
	}
	int st=1,ans=0;
	for(int i=1;i<=len;i++){
		vis[i]+=vis[i-1];
		while(a[st].l==i&&st<=n){
			Q.push(a[st].r);
			vis[i]++; vis[a[st].r+1]--;
			st++; ans++;
		}
		int op=vis[i]-e[i];
		if(op<=0)continue;
		while(op--){
			vis[Q.top()+1]--;
			Q.pop();
			vis[i]--;
			ans--;
		}
	}
	cout<<ans<<endl;
}
posted @ 2021-10-06 07:02  白木偶君  阅读(32)  评论(0编辑  收藏  举报