舞会

学校举行舞会啦,一共有N个人参加,所有人站成一排,从左开始编号,最左边的人编号为1,最右边的为N。每个人跳舞的熟练度我们用一个整数表示,第i个人的熟练度为Ai,每次熟练度最接近的一对相邻男女会出列跳舞,如果有多对那么最左边的那一对会先出列,请你给出出列跳舞的顺序。

输入
第一行一个整数N,第二行N个字符表示N个人的性别,‘1’表示男孩,‘0’表示女孩。第三行N个整数表示每人熟练度。
N<=200000.Ai<=10^7
输出
第一行一个整数k,表示一共出列k对人。
下面k行,第i行两个整数ai,bi(ai<bi),表示第i次出列的是编号为ai,bi的一对。

样例输入
4
1011
1 1 2 3

样例输出
1
1 2

 

#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
int a[200010],b[200010],nxt[200010],las[200010],in[200010],x[200010],y[200010];
inline int abs(int x) 
{
	return x<0?-x:x;
}
struct node 
{
	int x,y,w;
//	const{return w==a.w?x>a.x:w>a.w;}
};
bool operator < (node xx,node yy)
{
  if ( xx.w==yy.w) 
  //如果权值一样,按x从小到大 
     return xx.x>yy.x; 
  else
  //按权值从小到大 
     return xx.w>yy.w;	
}
	

priority_queue<node>q;//大根堆 
int main()
{
	int n;
	scanf("%d\n",&n);
	for(int i=1;i<=n;i++)
	{
		a[i]=getchar()-'0';
		in[i]=1;
	}
	for(int i=1;i<=n;i++)
		scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)
		nxt[i]=i+1,las[i]=i-1;
	for(int i=1;i<n;i++)
		if(a[i]!=a[i+1])
		    q.push((node){i,i+1,abs(b[i]-b[i+1])});
	int tot=0;
	while(!q.empty())
	{
		node t=q.top();
		q.pop();
		int xx=t.x,yy=t.y;
		if(!in[xx]||!in[yy]||a[xx]==a[yy])
		//如果xx不在队列中,或者yy不在队列中,或者两者性别是一样的 
		    continue;
		//否则记入答案中 
		x[++tot]=xx;
		y[tot]=yy;
		in[xx]=in[yy]=0;//出队列
		//a....xx.yy...b
		//设a的后继为b,b的前驱为a 
		xx=las[xx],yy=nxt[yy];
		nxt[xx]=yy,las[yy]=xx;
		if(in[xx]&&in[yy]&&a[xx]!=a[yy])
			q.push((node){xx,yy,abs(b[xx]-b[yy])});
	}
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
		printf("%d %d\n",x[i],y[i]);
	return 0;
}

  

posted @ 2020-10-08 10:36  我微笑不代表我快乐  阅读(150)  评论(0编辑  收藏  举报