Codeforces1249D2 Too Many Segments (hard version)

题目链接

https://codeforces.com/contest/1249/problem/D2

题目大意

给你 N 条线段,每条线段覆盖的点为 [Li ,  Ri] ,如果某个点被超过 k 条线段覆盖,那么这个点为坏点,

问最少可以去掉哪些线段可以使得没有坏点

解题思路

线段树 + multiset

挺水的一题。

很显然在满足 L <= 当前坏点位置时 ,删除 R 最大的线段是最优的

对于每个线段它覆盖的点为 [Li , Ri]  , 那么就用线段树对应维护这个区间内的所有点

在所有线段都操作完毕后再将坏点取出,以及对线段排序

然后遍历所有坏点 , 将左端点 L 小于当前坏点的线段存入 multiset ,存完后再删除其中 R 最大的几项即可

AC_Coder

#include<bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define int long long
#define ll long long
#define il inline 
#define fi first 
#define se second
#define pb push_back
using namespace std;
struct Tree
{
    ll l,r,sum,lazy,maxn,minn;
} tree[1000000];
il void push_up(ll rt)
{
    tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
    tree[rt].maxn=max(tree[rt<<1].maxn,tree[rt<<1|1].maxn);
    tree[rt].minn=min(tree[rt<<1].minn,tree[rt<<1|1].minn);
}
il void push_down(ll rt , ll length)
{
    if(tree[rt].lazy)
    {
        tree[rt<<1].lazy+=tree[rt].lazy;
        tree[rt<<1|1].lazy+=tree[rt].lazy;
        tree[rt<<1].sum+=(length-(length>>1))*tree[rt].lazy;
        tree[rt<<1|1].sum+=(length>>1)*tree[rt].lazy;
        tree[rt<<1].minn+=tree[rt].lazy;
        tree[rt<<1|1].minn+=tree[rt].lazy;
        tree[rt<<1].maxn+=tree[rt].lazy;
        tree[rt<<1|1].maxn+=tree[rt].lazy;
        tree[rt].lazy=0;
    }
}
il void build(ll l , ll r , ll rt , ll *aa)
{
    tree[rt].lazy=0;
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r)
    {
        tree[rt].sum=aa[l];
        tree[rt].minn=tree[rt].sum;
        tree[rt].maxn=tree[rt].sum;
        return;
    }
    ll mid=(l+r)>>1;
    build(l,mid,rt<<1,aa);
    build(mid+1,r,rt<<1|1,aa);
    push_up(rt);
}
il void update_range(ll L , ll R , ll key , ll rt)
{
    if(tree[rt].r<L||tree[rt].l>R)return;
    if(L<=tree[rt].l&&R>=tree[rt].r)
    {
        tree[rt].sum+=(tree[rt].r-tree[rt].l+1)*key;
        tree[rt].minn+=key;
        tree[rt].maxn+=key;
        tree[rt].lazy+=key;
        return;
    }
    push_down(rt,tree[rt].r-tree[rt].l+1);
    ll mid=(tree[rt].r+tree[rt].l)>>1;
    if(L<=mid)update_range(L,R,key,rt << 1);
    if(R>mid)update_range(L,R,key,rt << 1 | 1);
    push_up(rt);
}
il ll query_range(ll L, ll R, ll rt)
{
    if(L<=tree[rt].l&&R>=tree[rt].r)
    {
        return tree[rt].sum;
    }
    push_down(rt,tree[rt].r-tree[rt].l+1);
    ll mid=(tree[rt].r+tree[rt].l)>>1;
    ll ans=0;
    if(L<=mid)ans+=query_range(L,R,rt << 1);
    if(R>mid)ans+=query_range(L,R,rt << 1 | 1);
    return ans;
}
const int N = 2e5 + 10;
struct node
{
    int l , r , id;
    bool operator < (node const & a) const
    {
        if(l == a.l) return r < a.r;
        return l < a.l;
    }
} x[N];
int n , k , a[N] , b[N] , cnt;
multiset<pair<int , int>>s;
vector<int>ans;
signed main()
{ 
    cin >> n >> k;
    build(1 , N - 10 , 1 , a);
    rep(i , 1 , n)
    {
        cin >> x[i].l >> x[i].r;
        update_range(x[i].l , x[i].r , 1 , 1);
        x[i].id = i;
    }
    rep(i , 1 , N - 10)
    if(query_range(i , i , 1) >= k)
        b[++ cnt] = i;
    sort(x + 1 , x + 1 + n);
    int now = 1;
    rep(i , 1 , cnt)
    {
        while(x[now].l <= b[i] && now <= n) s.insert(make_pair(-x[now].r , x[now].id)) , now ++ ;
        int tot = query_range(b[i] , b[i] , 1) - k;
        while(tot > 0)
        {
            auto it = *s.begin();
            update_range(b[i] , -it.fi , -1 , 1);
            s.erase(it);
            tot -- ;
            ans.pb(it.se);
        }
    }
    cout << ans.size() << "\n";
    for(auto i : ans) cout << i << " ";
    cout << '\n';
    return 0;
}
posted @ 2020-06-01 17:21  GsjzTle  阅读(193)  评论(0编辑  收藏  举报