题解 P1878 【舞蹈课】
每次这群人里都要选择能力差值最小的一对男女来跳舞,而且组数也会有变化,所以我们想到了用堆优化
我们先将每一对相邻的异性之间能力的差值读入,然后用priority_queue来模拟堆
每当取出最上面的一对时要判断这一对是否合法(即这一对中是否有一人已经被配对。我们可以定义vis数组来记录是否是配对过。
这道题就是检验堆的使用的
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;
struct node{
int id;
bool fem;
int dan;
int pre;
int next;
};
struct de{
int d;
int ida;
int idb;
bool operator < (const de x) const{
if(d==x.d){
return ida>x.ida;
}
return d>x.d;
}
};
struct ptt{
int id1,id2;
};
int n,k;
int B,G;
int head;
int tail;
node peo[200010];
int vi[200010];
priority_queue<de> q;
int main(){
scanf("%d",&n);
peo[0].next=1;
for(int i=1;i<=n;i++){
peo[i].pre=i-1;
peo[i].next=i+1;
peo[i].id=i;
char c;
cin>>c;
if(c=='B'){
peo[i].fem=false;
B++;
}
else{
peo[i].fem=true;
G++;
}
}
head=0;
tail=n+1;
k=min(B,G);
for(int i=1;i<=n;i++){
scanf("%d",&peo[i].dan);
}
for(int i=1;i<n;i++){
if(peo[i].fem^peo[i+1].fem){
q.push((de){abs(peo[i].dan-peo[i+1].dan),i,i+1});
}
}
cout<<k<<endl;
int l=0;
while(!q.empty()){
de x=q.top();
q.pop();
if(vi[x.ida]|vi[x.idb]){
continue;
}
cout<<x.ida<<" "<<x.idb;
l++;
if(l==k) break;
cout<<endl;
vi[x.ida]=vi[x.idb]=1;
int a=peo[x.ida].pre,b=peo[x.idb].next;
if(peo[a].fem^peo[b].fem){
if(a<=0||b>n) continue;
q.push((de){abs(peo[a].dan-peo[b].dan),a,b});
}
}
return 0;
}