ZOJ 4120 Tokens on the Segments ( 优先队列 + 思维 )

题目链接
在这里插入图片描述
大致题意:
在一个平面上给你 n n n 条线段的左右端点的横坐标(可重叠),纵坐标为当前是第几条,即两点坐标为 ( l , i ) (l,i) (l,i) ( r , i ) (r,i) (r,i) ,你可以在平面的任意整数坐标位置放置一个标记,标记的横坐标不可相同.问最给定的线段最多会被标记多少条。

解题报告:
贪心 ,对于某位置 x x x 的标记,我们肯定会左端点小于等于 x x x 且右端点大于等于 x x x,满足这样的线段可能有很多条,根据贪心性质肯定优先选择右端点较小的(优先队列维护),这样做能让右端点较大的在更右位置获得标记的可能性。
代码展示:

#include<bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define wp(x) write(x),putchar('\n')
#define wpl(x) write(x),putchar(' ')
#define mem(a, b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 3e5 + 5;
const int MOD = 998244353;

inline int read() {
	int s = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {s = (s << 1) + (s << 3) + ch - '0'; ch = getchar();}
	return s * f;
}
inline void write(int x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
struct node{
	int x,y;
	node(){}
	node (int _x,int _y){
		x=_x;y=_y;
	}
	bool operator < (const node &ls) const {
		if(ls.x==x) return ls.y<y;
		return ls.x<x;
	}
};
priority_queue<node>q;
int main() {
	int T=read(),n,x,y;
	while(T--){
		n=read();
		for(int i=1;i<=n;i++){
			x=read();y=read();
			q.push(node(x,y));
		}
		int ans=0,st=0;
		node pp;
		while(!q.empty()){
			pp=q.top();q.pop();
			if(st<=pp.y){
				ans++;
				if(st<pp.x) st=pp.x+1;
				else st++;
			}
			// 更新与之前左端点相同的点 令其 +1
			while(!q.empty()&&q.top().x==pp.x){
				node tt=q.top();q.pop();
				tt.x++;
				if(tt.x<=tt.y) q.push(tt);
			}
		}
		wp(ans);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值