D1. Too Many Segments (easy version)

题目:样例1:

输入
7 2
11 11
9 11
7 8
8 9
7 8
9 11
7 9

输出
3
1 4 7 

样例2:

输入
5 1
29 30
30 30
29 29
28 30
30 30

输出
3
1 2 4 

样例3:

输入
6 1
2 3
3 3
2 3
2 2
2 3
2 3

输出
4
1 3 5 6 

思路:

                这里数据范围是 200,所以我们完全可以暴力遍历每一个点是否在该区间内,这里需要注意的是,可以通过差分的方式达到区间总和的变化,所以要学会掌握好差分。

代码详解如下:

#include <iostream>
#include <unordered_map>
#define endl '\n'
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;

struct Range
{
	int l,r;
}a[N];

int n,m;
umap<int,int>b;
umap<int,bool>r;
inline void solve()
{
	cin >> n >> m;
	for(int i = 1;i <= n;++i)
	{
		int l,r;
		cin >> l >> r;
		
		// 差分数组
		++b[l];
		--b[r + 1];
			
		a[i] = {l,r};
	}	
	
	// 差分前缀和,构造出每一个点所在位置的当前点前缀总和
	for(int i = 1;i <= 200;++i) b[i] += b[i - 1];
	
	int sz = 0;		// 删除线段数量
	
	// 开始遍历每一个点
	for(int i = 1;i <= 200;++i)
	{
		// 如果当前线段所在的点有超过了规定可重合部分 m
		// 则开始选择删除
		while(b[i] > m)
		{
			int tem = 0;	// tem 作为探头,探索哪一个需要删除的
			// 开始遍历每一个线段,寻找合适删除的线段
			for(int j = 1;j <= n;++j)
			{
				// 如果当前线段范围更广,那么应该删除,tem = j
				if(a[j].l <= i && a[j].r >= i && (!tem || a[j].r > a[tem].r) && !r[j]) tem = j;
			}
			
			// 标记已选择删除的线段
			r[tem] = true;
			
			// 累加删除线段
			++sz;
			
			// 更新区间所在点的覆盖线段数量
			for(int j = a[tem].l;j <= a[tem].r;++j) --b[j];
		}
	}
	
	// 输出答案,删除的线段
	cout << sz << endl;
	for(int i = 1;i <= 200;++i)
	{
		if(r[i]) cout << i << ' ';
	}
}


int main()
{
//	freopen("a.txt", "r", stdin);
	___G;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值