双索引应用(直接硬做,遍历整个过程,开始,下一个,重排)

链接:https://ac.nowcoder.com/acm/contest/18453/F
来源:牛客网

题目描述
Professor O’Dagio of the music department at Faber College has come up with a rather interesting way of selecting its department chair. All n members of the music faculty line up, then the first one in line calls out an integer k corresponding to the opus number of his or her favorite musical composition by Faber College’s most illustrious alumnus, composer I. M. Tondeff. The department members then “count off,” starting with the first in line and cycling back to the beginning of the line if necessary. When the count reaches k, that person steps out of the line and is relieved (in more than one sense!) of chairmanship duty for that year.
The next person in line then calls out his or her favorite opus number (this becomes the new value of k) and the count restarts at “1,” and continues until the next person is eliminated, and so on. When only one faculty member is left standing, this is the new department chair. To prevent cheating, everyone’s favorite number is announced in advance and no one is allowed to choose Tondeff’s Opus 1 (the famous drinking song Rhapsody in Brew).
For instance, suppose the professors are numbered 1 through 4 and lined up in that order; suppose their favorite opus numbers are, respectively, opus 8 (The Four Sneezings), opus 2 (Concerto for Kazoo and Cigar Box Banjo), opus 4 (The Taekwondo Rondo), and opus 2 (again). Figure F.1 shows the process by which the new chair is selected.

Figure F.1: Example of Selection Process
输入描述:
The first line of input contains an integer n (2 ≤ n ≤ 104 ), the number of faculty members. The next line contains n integers k1 . . . kn (2 ≤ ki ≤ 106 for each i), where ki is the favorite opus number of professor i.
输出描述:
Output the number of the new department chair.
示例1
输入
复制
4
8 2 4 2
输出
复制
3
题解:本题开始想找规律做,后来发现找不到。。。。直接硬做呗,不过硬座也要有所依据,利用双索引,一变一不变。
双索引:本身自带的,如V[i]中的i;自加的,如v[i].id。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=1e5+5;
struct node{//可能用数组也行,不过结构体不容易乱
	ll num;
	ll k=1;用于标记删除的数据
	ll id;
};
node v[nl];
int main(){
	ll n;
	cin>>n;
	ll i,j;
	for(i=0;i<n;i++){
		ll f;
		cin>>f;
		v[i].num=f;
		v[i].id=i+1;//增加一个索引,操作中会不断改变它
	}
	ll z=n;
	ll t=0;
	while(z>1){
		ll kl=v[t].num;
		ll ml=kl%z;
		if(ml==0){
			ml=z;
		} 
		// 删除数据
		for(i=0;i<n;i++){
			if(v[i].id==ml&&v[i].k==1){//这里用.id这个索引,因为由于删除数据,其他数本身索引顺序会改变。
				v[i].k=0;
				t=i;
				z--;
				break;
			}
		}
		// 指向被删除的数据的下一个位置(v[i].k==1)
		for(i=1;i<n;i++){
			ml=(t+i)%n;
		    if(v[ml].k==1){
		    	t=ml;
		    	break;
			}
		}
		// 重新排列索引
		v[ml].id=1;
		ll s=1;
		for(i=1;i<n;i++){
			ml=(t+i)%n;
			if(v[ml].k==1){
				s++;
				v[ml].id=s;
			}
			if(s==z){
				break;
			} 
		}
	}
	cout<<t+1<<endl;//这里感觉也很巧妙(因为我比较菜。。。),利用t(最后指向被删除的数据的下一个数据(v[i].k==1))
}

另一种做法:运用vector内置函数,算法复杂度差不多,不过这个看起来更简单明了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=1e5+5;
vector<ll >v;
vector<ll >v1; 
int main(){
	ll n;
	cin>>n;
	ll i,j;
	for(i=0;i<n;i++){
		ll f;
		cin>>f;
		v.push_back(i+1);
		v1.push_back(f);
	}
	ll sum=n;
	ll cnt=0;
	for(i=0;i<n;i++){
		ll x=(v1[cnt]-1)%sum;
		x=(x+cnt)%sum;
		std::vector<ll>::iterator it= v.begin()+x;
		v.erase(it);
		it=v1.begin()+x;
		v1.erase(it);
		cnt=(x+1)%sum;
		if(cnt>x){
			cnt--;
		}
		sum--;
	}
	cout<<v[0];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值