地址:https://judge.icpc.global/problems/azulejos
题目大意:有两排盘子,盘子有价格pi和高度hi。
盘子的放置规则为:每排的盘子按照价格从小到大排列,对于第二排的盘子的高度必须比第一排对于列的盘子高度高(h2i>h1i)
输入
每排盘子的个数 n
第二排盘子的价格
第二排盘子的高度
第一排盘子的价格
第一排盘子的高度
输出
若能够按规则放置则输出
第二排盘子的id (id按输入顺序由 1->n)
第一排盘子的id
否则输出 "impossible"
思路:贪心+STL (STL大法好啊 ^v^ )
首先对于每排盘子按照价格排序,那么不同价格的盘子的放置顺序已经固定,
那么问题的关键就是对于不固定盘子(相同价格的盘子)的放置顺序。
对于两排相同价值的盘子分析
对第i列有三种情况如图 (长方形表示不固定的盘子集)
一、第二排盘子固定,第一排不固定,利用贪心思想,第一排的盘子放置一个高度最高且小于第二排的盘子高度即为最佳方式
二、一二排的盘子都不固定,那么相同价格盘子的个数少的一排会被消耗掉,则只需要按贪心保证第二排高度大于第一排高度即可
三、第一排盘子固定,第二排不固定,利用贪心思想,第二排的盘子放置一个高度最低且大于第一排的盘子高度即为最佳方式
先利用map处理出每一排的不同价值盘子的个数并由小到大排序
对于贪心解法,可以利用二分查找来找出最佳方式,而已经放置的盘子需要去除掉
而set可以进行排序,二分查找以及删除操作,则可以用set结构来存储即可 ( ̄▽ ̄)~*
Code :
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
typedef pair<int,int> pr;
const int MAX_N=5e5+5;
int n,T;
int d[2][MAX_N];
map<int,set<pr>> a,b;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int j=0;j<n;++j)
cin>>d[0][j];
for(int j=0,x;j<n;++j)
{
cin>>x;
a[d[0][j]].insert({x,j+1});
}
for(int j=0;j<n;++j)
cin>>d[0][j];
for(int j=0,x;j<n;++j)
{
cin>>x;
b[d[0][j]].insert({x,j+1});
}
bool boo=true;
int a1=0,b1=0;
int sa,sb,k;
set<pr> aa,bb;
set<pr>::iterator si;
map<int,set<pr>>::iterator ai=a.begin(),bi=b.begin();
for(int t=0;ai!=a.end()&&boo;)
{
if(!a1) aa=(*ai).second;
if(!b1) bb=(*bi).second;
sa=aa.size(); sb=bb.size();
if(sa<sb){
for(auto c:aa)
{
si=bb.lower_bound({c.first,0});
if(si!=bb.begin()){
d[0][t]=c.second;
d[1][t]=(*--si).second;
++t;
bb.erase(si);
}else{
boo=false; break;
}
}
++ai;
a1=0; b1=1;
}else{
for(auto c:bb)
{
si=aa.lower_bound({c.first+1,0});
if(si!=aa.end()){
d[0][t]=(*si).second;
d[1][t]=c.second;
++t;
aa.erase(si);
}else{
boo=false; break;
}
}
++bi;
a1=1; b1=0;
}
}
if(boo){
for(int i=0;i<2;++i)
{
for(int j=0;j<n-1;++j)
cout<<d[i][j]<<" ";
cout<<d[i][n-1]<<endl;
}
}else cout<<"impossible"<<endl;
return 0;
}