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; }
凡所不能将我击倒的,都将使我更加强大