cf 1249 D2. Too Many Segments (hard version) (贪心+multiset)

题意:

有n条线段,每条线段覆盖的点为[li,ri],如果点被超过k条线段覆盖,那么这个点为坏点,

问,最少去掉哪几条线段,可以使得没有坏点?

思路:

点从左往右扫,如果这个点为坏点,那么就去掉一些 覆盖这个点的线段,从ri最大的开始删,不需要考虑li是因为你已经保证左边没有坏点了,那么删掉的线段当然是ri越大越好。

用multiset维护当前覆盖这个点的线段是哪几条。

今天才知道,sort的时候,外部定义的cmp函数可以覆盖结构体里的重载运算符'<'。

果然不是大佬就少用stl,测样例的时候RE,交了两发也RE,调好久。

代码:

#include <stdio.h>
#include <string.h>
#include <cmath>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
typedef long long int ll;
const double pi = acos(-1);
const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f;
struct node
{
    int l,r,id;
    friend bool operator <(node x,node y){
        return x.r < y.r;
    }
}a[maxn];

bool cmp(node x,node y)
{
    return x.l < y.l;
}
int vis[maxn];
multiset<node>st;
int main()
{
    multiset<node>::iterator it;
    int n,k,ans,mx;
    while(scanf("%d%d",&n,&k) != EOF){
        ans = 0;
        mx = 0;
        st.clear();
        memset(vis,0,sizeof(vis));
        for(int i = 1;i <= n;i++){
            scanf("%d%d",&a[i].l,&a[i].r);
            mx = max(mx,a[i].r);
            a[i].id = i;
        }
        sort(a + 1,a + n + 1,cmp);
        int cnt = 1,now = 0;
        for(int i = 1;i <= mx;i++){
            it = st.begin();
            while(it != st.end() && (*it).r < i){
                st.erase(it);
                it = st.begin();
                now--;
            }
            while(cnt <= n && a[cnt].l <= i){
                st.insert(a[cnt]);
                cnt++;
                now++;
            }
            it = st.end();
            while(now > k){
                it--;
                vis[(*it).id] = 1;
                st.erase(it);
                
                it = st.end();
                now--;
                ans++;
            }
        }
        printf("%d\n",ans);
        for(int i = 1;i <= n;i++){
            if(vis[i])
                printf("%d ",i);
        }
        puts("");
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/InitRain/p/12445914.html