题解 CF45C 【Dancing Lessons】
Description
给出长度为
Solution
看到序列中的删除操作,就能想到用链表去维护这个序列,而求舞蹈技术差值最小,则可以用优先队列去维护,将差值最小的放在最上面,每次求的时候在更新一下链表即可
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int pre[N], nex[N], a[N], fl[N];//fl数组用来标记当前位置是否使用
char s[N];
int n, cnt, ans[N][2];
struct node{
int l, r, d;
node(int L, int R, int D):l(L), r(R), d(D){}
bool operator <(const node &o)const{
return d == o.d ? l > o.l : d > o.d;//当二者差值相同时,按照l排序
}
};
priority_queue<node> q;
template <typename T>
inline void read(T &x){
char t(getchar()), flg(0); x = 0;
for (; !isdigit(t); t = getchar() ) flg = t == '-';
for ( ; isdigit(t); t = getchar() ) x = x * 10 + ( t & 15 );
flg ? x = -x : x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args){read(x);read(args...);}
int main(){
read(n);
scanf("%s", s + 1);
for(int i = 1; i <= n; ++i)
read(a[i]), pre[i] = i - 1, nex[i] = i + 1;//初始化
for(int i = 1; i < n; ++i)
if(s[i] != s[i + 1])
q.push(node(i, i + 1, abs(a[i] - a[i + 1])));
//当两者性别不同时,即可插入优先队列
while(!q.empty()){
node tmp = q.top(); q.pop();//取出差值最小
if(fl[tmp.l] || fl[tmp.r]) continue;//若当前节点访问过,就可以跳过
ans[++cnt][0] = tmp.l, ans[cnt][1] = tmp.r;
fl[tmp.l] = fl[tmp.r] = 1;
int L = pre[tmp.l], R = nex[tmp.r];
nex[L] = R, pre[R] = L;//维护链表
if(L < 1 || R > n) continue;
if(s[L] != s[R])
q.push(node(L, R, abs(a[L] - a[R])));
}
printf("%d\n", cnt);
for(int i = 1; i <= cnt; ++i)
printf("%d %d\n", ans[i][0], ans[i][1]);
}