zoukankan      html  css  js  c++  java
  • 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() << "
    ";
        for(auto i : ans) cout << i << " ";
        cout << '
    ';
        return 0;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    多校赛3- Painter 分类: 比赛 2015-07-29 19:58 3人阅读 评论(0) 收藏
    K
    Drainage Ditches 分类: POJ 图论 2015-07-29 15:01 7人阅读 评论(0) 收藏
    Power Network 分类: POJ 2015-07-29 13:55 3人阅读 评论(0) 收藏
    Labeling Balls 分类: POJ 2015-07-28 19:47 10人阅读 评论(0) 收藏
    Network 分类: POJ 图论 2015-07-27 17:18 17人阅读 评论(0) 收藏
    Borg Maze 分类: POJ 2015-07-27 15:28 5人阅读 评论(0) 收藏
    Case of the Zeros and Ones 分类: CF 2015-07-24 11:05 15人阅读 评论(0) 收藏
    滑雪 分类: POJ 2015-07-23 19:48 9人阅读 评论(0) 收藏
    Wormholes 分类: POJ 2015-07-14 20:21 21人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13026255.html
Copyright © 2011-2022 走看看