【解题报告】【】交谊舞

                                      Title:交谊舞

Description

描述 明显……交谊舞是2个人跳的,而且一男一女 -__-||||。 由于交谊舞之前的节目安排,所有的表演者都站成了一排。这一排人的顺序满足2点:

  • 对于一对舞伴男生站在女生的左边。
  • 任何一对舞伴之间,要么没有人,要么就有若干对舞伴。

排得过于整齐导致那些要表演交谊舞的人都没办法看到自己的舞伴,怎么办类……. 所幸的是,SDFZ的女生比男生聪明得多。她们知道自己左边有几个男生。 现在就请你再告诉这些女生,她们的舞伴距离她们多远(即包括那个男生,一共有多少男生夹在他们之间)。

Input Format

输入格式

第一行为一个数n,表示参与跳交谊舞的女生个数。

第二行n个数,从左到右表示这n个女生左边分别有多少个男生。

Output Format

输出格式

一排n个数,行末无空格。表示n个女生与其舞伴的距离。

Sample Input

6
4 5 6 6 6 6

Sample Output

1 1 1 4 5 6

Hint

各个测试点1s

n<=1500,结果小于2^31-1

Analysis

算法:贪心+模拟

简析:女生选舞伴的原则,往左找第一个未被挑选的男生(若找非第一个未被挑选的男生,则之间必然经过第一个没被挑选的男生,不符合中间是成对舞伴的条件)

做法:s[i]记录到i女生在所有人中的编号
           man[i]记录i女生左边共有多少男生
           c[i]记录可供选择的男生区间,并保证c[i]递增,c[i].l,c[i].r为区间的左右边界,c[i].now为该区间可取的为c[i].l-->c[i].now
           枚举1-n个女生,若man[i]>man[i-1]说明多出了一个可供选择的男生区间,则加入c[i](加入的是男生在全部人中的编号)
           接着输出c[tot]中可供选择的男生,若该区间已被取完则tot--,直到找到可供选择的区间。
 
注意:c[i]记录的是男生在全部人中的编号,所以计算起来较复杂
 
复杂度:O(n^2)

Code

</pre></h2></div></div><div class="markdown" style="text-indent:2em"><pre name="code" class="cpp">//by king QZqz 
#include<cstdio>
#include<algorithm>
#include<cstring>
const int N=1600;
struct data{
	int l,r,now;
}c[N];
int man[N],s[N],n,lastman,tot;
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&man[i]);
		s[i]=s[i-1]+1+man[i]-man[i-1];
	}//man[i]-man[i-1]是在i和i-1之间的男生,+s[i-1]+1,就是到i女生在所有人中的编号 
	man[0]=0;
	for (int i=1;i<=n;i++)
	{
		if (man[i]>man[i-1])//多了可供选择的男生区间 
		{
			tot++;
			c[tot].l=man[i-1]+i;//左边界,男生+女生得到该区间男生的初始编号 
			c[tot].now=c[tot].r=c[tot].l+man[i]-man[i-1]-1;
			//右区间为左区间加上i和i-1之间的男生(新增男生人数)-1(扣去i女生本身) 
		}
	    while (c[tot].now<c[tot].l&&tot>=1) tot--;//找到一个可供选择c[tot].now(舞伴的编号)
	    int j=1;
	    while (s[j]<c[tot].now) j++;//用于计算c[tot].now(男)和i(女)之间的女生人数 
		printf("%d ",man[i]+i-c[tot].now-(i-j));
		//man[i]+i(总人数)-c[tot].now(男生编号)=这对舞伴之间的总人数(不算i)
		//(i-j)这对舞伴之间的女生人数(不算i),以上两项相减即为男生人数 
	    c[tot].now--;
	    while (c[tot].now<c[tot].l&&tot>=1) tot--;
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值