P1878

· · 题解

首先定义一个people结构体,用于存储一对舞者的数据。 记得重载运算符,依据是舞蹈技术的差的大小。

输入的时候判断一下,如果性别不同就加入堆。

之后只要堆不是空的就一直循环。

记录堆顶的一对人。

只要两人都还没跳过舞,就让他们跳舞,就更新答案。

之后往左右找还在队里的人(因为跳完舞就出队所以现在他们就是相邻的了)。 找到了就入堆,没找到就执行下一对。

code(详细注释):

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
char ch[200003];//输入性别的字符数组 
int a[200003];//输入舞蹈能力的数组 
bool vis[200003];//判断是否还在队中 
int ans1[200003],ans2[200003],t;//ans1和ans2存储答案,t存储答案数量 
struct people{
    int cha,x,y;//x和y分别是一组舞伴的编号,cha是他们舞蹈技术的差 
    friend bool operator < (people b,people c){
        //我们重新定义小于号,让舞蹈技术差最小的一对最靠前,如果有技术差一样的,编号小的靠前 
        if(b.cha==c.cha) return b.x>c.x;//如果两人舞蹈技术差一样,编号越小的越大 
        else return b.cha>c.cha;//否则技术差小的靠前 
    }
};
priority_queue<people> q;//定义一个people类型的大根堆 
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>ch[i];
    }//输入数据 
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(i!=1&&ch[i]!=ch[i-1]){//如果两人相邻且性别不同,入堆 
            q.push(people{abs(a[i-1]-a[i]),i-1,i});
        }
    }
    while(!q.empty()){//堆还没空 
        int x=q.top().x; 
        int y=q.top().y;//记录堆顶元素
        q.pop();//pop掉 
        if(!vis[x]&&!vis[y]){//如果两人还在队中 
            vis[x]=1;
            vis[y]=1;//标记出队 
            t++;//答案总数加一 
            ans1[t]=x;
            ans2[t]=y;//记录答案 
            while(x>=1&&vis[x]) x--;
            while(y<=n&&vis[y]) y++;//往左右继续找未出队的人 
            if(x<1||y>n) continue;//如果越界,就执行下一个 
            if(ch[x]!=ch[y])//如果不越界且性别不同,入堆 
            q.push(people{abs(a[x]-a[y]),x,y});
        }   
    }
    printf("%d\n",t);//输出t 
    for(int i=1;i<=t;i++) printf("%d %d\n",ans1[i],ans2[i]);//输出答案 
}