牛客IOI周赛22-普及组 签订协议(c++)

签订协议

点我跳转原题

一共有n个国家来到了停战点,在协议停战签订的会场里,环形排布着n个位置, 位置从1开始编号,一直到n号,每个位置上有一个国家。

签订停战协议的仪式开始了,停战协议书从1号位置开始传递,一直传递到n号位置, 传到n号时,n号会再传回给1号,从而开始新的一轮传递。 停战协议签订的顺序必须按照国家的战力来排序,战力最高的最先签订停战协议。
也就是说,如果停战协议轮到了某个国家,但该国家并不是在场还未签订协议的国家中战力最强的,那么他这轮只能轮空,传给下一个国家。 协议只能单向传递,不可逆传,协议书每次从n号传到1号手上算是一轮。不满一圈的也算一轮。各个国家战力保证不相同。为了停战协议的顺利签订,会场组织者向你求助,求最少传递多少轮可以完成协议的签订。

输入描述:

第一行,一个正整数 n,表示有 n 个国家参与
第二行n个正整数,第 ai个数表示落座在第 i 个位置的国家的战力值
输出描述:
第一行,一个正整数,完成签订协议的最少轮数。

解题思路:

这个思路其实也不是我想出来的,我是看题解时发现的,但是他并没有特别明确的说明这个方法的原由,所以我就解释一下
定义一个结构体,记录它的值和在原队列中的位置
然后定义一个cmp函数,当我sort时使原队列递减排列
此时越前面的数越大
关键来了,如果有一个战斗力大的国家位置靠后,那么就只能先让这个国家签订,而当前国家需要等下一轮
也就是处理后数组中前一个数的初始位置如果>后一个数的初始位置,那么要前让后面的“国家”签订协议,然后再从头开始,也就是轮数加一(你品,你细品)
明白了这一层其他的就很好处理了

AC代码:

#include <cstdio>
#include <algorithm>
using namespace std;
struct Nebula {
    
    
	int x,id;
} s[800001];
bool cmp(Nebula a,Nebula b) {
    
    
	return a.x>b.x;
}//定义sort后数组按递减排序
int main() {
    
    
	int n;//输入数据
	scanf("%d",&n);
	for(int i=1; i<=n; i++) {
    
    
		scanf("%d",&s[i].x);
		s[i].id=i;//输入x时借用i来输入id
	}
	sort(s+1,s+1+n,cmp);//数组处理重新排序
	int count=0;
	for(int i=1; i<=n; i++) {
    
    
		if(s[i].id>s[i+1].id)//如果排序后的前一个数最开始在后一个数后面,轮数加一
			count++;
	}
	printf("%d",count);//输出答案
}

附:初来乍到,如果有不足之处,恳请各位大牛指正,如果题解有错误或者没写清楚的地方也欢迎在评论区提问~

猜你喜欢

转载自blog.csdn.net/qq_34832548/article/details/113100529