1. 程式人生 > >Codeforces Round #595 (Div. 3)D1D2 貪心 STL

Codeforces Round #595 (Div. 3)D1D2 貪心 STL

一道用STL的貪心,正好可以用來學習使用STL庫

題目大意:給出n條可以內含,相交,分離的線段,如果重疊條數超過k次則為壞點,n,k<2e5

所以我們貪心的想我們從左往右遍歷,如果重合部分條數超過了k,就必須去除線段,(此時從左邊看去除線段後不會出現衝突,右邊還有剩餘很多線段未知)所以我們選擇去除這些重合線段裡右端最右的部分

實現:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn =2e5+30;
set<pii>res;

vector<pii>v[maxn];
vector<int>ans;
int main(){
int n,k,mx=0,t1,t2;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d%d",&t1,&t2);
v[t1].push_back({t2,i});//左端點t1儲存右端點和序號i,C11的用法這裡{t2,i}等於make_pair
mx=max(t2,mx);
}
for(int i=0;i<=mx;i++){
while(res.begin()->first <i&&!res.empty())//當右端點小於i時已經完全掃過,此時刪去該線段
res.erase(res.begin());//刪去整條線段
for(int j=0;j<v[i].size();j++)
res.insert(v[i][j]);//插入該端點為左端點下的線段
while(res.size()>k){//如果此時重合部分大於k,則找到這些線段裡右端點最右的線段,加入ans並刪去
ans.push_back(res.rbegin()->second);//rbegin()返回的是最末元素的位置
res.erase(--res.end());//注意雖然效果一樣但end和rbegin的型別不一樣
}
}
cout<<ans.size()<<endl;
for(auto x:ans){
cout<<x<<' ';
}
cout<<endl;
}

原題連結:https://codeforces.com/contest/1249/problem/D2

關於迭代器的tip

 

&n