D1. Too Many Segments (easy version)

题目:D1. Too Many Segments (easy version)_第1张图片样例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 
#include 
#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;
umapb;
umapr;
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;
}

最后提交:

你可能感兴趣的:(玩转上号CF“游戏”,算法错题本,算法,c语言)