codeforces round 283(div.2) E(multiset的使用,将结构体存入multiset 的方法,迭代器的使用,不断的将合法的数据存入set中然后进行查找)
https://codeforces.com/contest/496/problem/E
题意
有n个区间和m个区间,现在要让n个区间包含于m个区间内,m个区间中第i个区间只能用ki次现在按n个区间的顺序输出对应区间包含在m个区间中的哪个区间
解题思路
先对两个区间的右边进行排序,然后遍历m个区间,每次遍历就将n个区间中右边小于等于该次遍历的区间的右边的数存入multiset中,存完后用lower_bound()找到第一个大于该遍历区间左边的multiset里的区间,由于存入时右边就小于等于遍历的区间,故选中的multiset里的区间一定包含于遍历的区间,故可以把被遍历区间的编号存入vector
代码
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define int long long
#define inf 1e18
using namespace std;
int Pow(int a,int b){
int t=1ll;
while(b){
if(b&1){
t=t*a;
}
b>>=1;
a=a*a;
}
return t;
}
struct ac{
int x;
int y;
int k;
int id;
bool operator<(const ac &z)const{return x<z.x;}//用于set中的排序
};
bool cmp(ac a,ac b ){
return a.y<b.y;
}
void solve(){
int n;
cin>>n;
vector<ac>a(n+1);
for(int i=1;i<=n;i++){
struct ac t;
cin>>t.x>>t.y;
t.id=i;
a[i]=t;
}
int m;
cin>>m;
vector<ac>b(m+1);
vector<int>ans(n+1);
for(int i=1;i<=m;i++){
cin>>b[i].x>>b[i].y>>b[i].k;
b[i].id=i;
}
multiset<ac>s;
sort(a.begin()+1,a.begin()+n+1,cmp);
sort(b.begin()+1,b.begin()+m+1,cmp);
int j=1;
for(int i=1;i<=m;i++){
while(j<=n&&a[j].y<=b[i].y){
ac t;
t.id=a[j].id;
t.x=a[j].x;
s.insert(t);//multiset对struct的排序
j++;
//if()
}
while(b[i].k){
auto it=s.lower_bound({b[i].x,0});
if(it==s.end()){
break;
}
ans[it->id]=b[i].id;
s.erase(it);
b[i].k--;
}
}
for(int i=1;i<=n;i++){
if(ans[i]==0){
cout<<"NO"<<endl;
return ;
}
}
cout<<"YES"<<endl;
for(int i=1;i<n+1;i++){
cout<<ans[i]<<' ';
}
cout<<endl;
}
signed main() {
ios::sync_with_stdio(0);
cout.tie(0),cin.tie(0);
int test=1;
//cin>>test;
while(test--)
solve();
return 0;
}
总结
1.迭代器用auto进行赋值,如果容器存储的是struct这种,则可以it->first访问
2.结构体存储进set中需要重载运算符bool operator<(const ac &z)const{return x<z.x;}
3.可能有用的小技巧:对于区间题,或许可以将两个数化为平面直角坐标系中的一个点,这样做或许有助于题目的理解
4.这个题目的主要思想是将一边的条件进行限定,再讨论另一边
5.讨论问题要从微观到宏观,微观更加容易讨论