Too Many Segments (easy version) CodeForces - 1249D1(贪心+差分)

题意

给多组线段,而每一个点的覆盖次数不超过K,每次可去除一个线段,问最少去多少线段以及线段的位置。
The only difference between easy and hard versions is constraints.

You are given nn segments on the coordinate axis OX. Segments can intersect, lie inside each other and even coincide. The ii-th segment is [li;ri] (li≤ri) and it covers all integer points jj such that li≤j≤ri.

The integer point is called bad if it is covered by strictly more than k segments.

Your task is to remove the minimum number of segments so that there are no bad points at all.

Input
The first line of the input contains two integers nn and kk (1≤k≤n≤200) — the number of segments and the maximum number of segments by which each integer point can be covered.

The next nn lines contain segments. The ii-th line contains two integers lili and riri (1≤li≤ri≤200) — the endpoints of the ii-th segment.

Output
In the first line print one integer mm (0≤m≤n) — the minimum number of segments you need to remove so that there are no bad points.

In the second line print mm distinct integers p1,p2,…,pm(1≤pi≤n) — indices of segments you remove in any order. If there are multiple answers, you can print any of them.

Examples
Input
7 2
11 11
9 11
7 8
8 9
7 8
9 11
7 9
Output
3
1 4 7
Input
5 1
29 30
30 30
29 29
28 30
30 30
Output
3
1 2 4
Input
6 1
2 3
3 3
2 3
2 2
2 3
2 3
Output
4
1 3 5 6

官方题解:

In this problem, the following greedy solution works: let’s find the leftmost point covered by more than kk segments. We should fix it somehow. How to do it? Let’s find some segment that was not removed already, it covers this point and its rightmost end is maximum possible, and remove this segment.
You can implement it in any time you want, even in O(n3) naively.

百度翻译:

在这个问题中,下面的贪婪解决方案是有效的:让我们找到被超过k段覆盖的最左边的点我们应该设法解决它。怎么做?让我们找到一些尚未被删除的段,它覆盖了这一点,它的最右边是最大可能的,并删除这个段。
你可以在任何时候实现它,即使是在O(n3)中。

思路

用差分数组找到每个点的覆盖次数,若超过k次则去掉几个右边较大的(因为是从左到右,所以不用考虑左边)

AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=300;
int n,k,d[N],num;
struct node
{
    int u,v;
} s[N];
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        memset(d,0,sizeof(d));
        int mx=-1;
        for(int i=1; i<=n; i++)/*差分数组*/
        {
            scanf("%d %d",&s[i].u,&s[i].v);
            mx=max(mx,s[i].u);
            mx=max(mx,s[i].v);
            d[s[i].u]++;
            d[s[i].v+1]--;
        }
        for(int i=1; i<=mx; i++)
            d[i]+=d[i-1];  //差分求每个点被覆盖值
        int book[N];
        memset(book,0,sizeof(book));
        int flag=0;
        num=0;
        for(int j=1; j<=mx; j++)
        {
            while(d[j]>k)
            {
                flag=1;
                int tab=0;
                for(int i=1; i<=n; i++)/*从n条边中找到i所处的线段,并在所有的线段中找到最右边最大的那个线段*/
                {
                    if(book[i]==0&&s[i].u<=j&&j<=s[i].v&&(tab==0||s[i].v>s[tab].v))
                        tab=i;
                }
                if(tab==0)
                    break;
                for(int i=s[tab].u; i<=s[tab].v; i++)
                    d[i]--;
                book[tab]=1;
                num++;
            }
        }
        if(flag==0)
            printf("0\n");
        else
        {
            printf("%d\n",num);
            for(int i=1; i<=n; i++)
                if(book[i])
                    printf("%d ",i);
            printf("\n");
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值