题目链接:luogu P1878 舞蹈课
题目大意:
题解:
选出所有相邻的异性,将他们存入优先队列中,按照舞蹈技术差值排序,每次选出堆顶的异性对,将答案加上他们的舞蹈技术差值,并标记他们的位置,再寻找离他们最近的没有被选择过的另一对异性,存入优先队列中。
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define N 200000 + 10
bool sex[N], vis[N];
string s;
int n, a[N], sum;
vector <pair<int, int> > ans;
struct Node {
int a, b, w;
bool operator < (const Node &x) const {
if (w == x.w) {
return a > x.a;
} else {
return w > x.w;
}
}
};
priority_queue <Node> q;
int main() {
io_speed_up;
cin >> n;
cin >> s;
int len = s.length();
for (int i = 0; i < len; ++i) {
if (s[i] == 'G') {
sex[i + 1] = false;
} else {
sex[i + 1] = true;
}
}
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
for (int i = 1; i < n; ++i) {
if (sex[i] != sex[i + 1]) {
q.push(Node{i, i + 1, abs(a[i] - a[i + 1])});
}
}
while (!q.empty()) {
Node temp = q.top();
q.pop();
int x = temp.a, y = temp.b;
if (vis[x] || vis[y]) continue;
vis[x] = true;
vis[y] = true;
sum++;
ans.push_back(make_pair(x, y));
while (x > 0 && vis[x]) x--;
while (y <= n && vis[y]) y++;
if (x > 0 && y <= n && sex[x] != sex[y]) {
q.push(Node{x, y, abs(a[x] - a[y])});
}
}
cout << sum << endl;
for (int i = 0; i < sum; ++i) {
cout << ans[i].first << ' ' << ans[i].second << endl;
}
return 0;
}