最新文章
这里会显示最新的几篇文章摘要。
记录生活,分享知识,与你一起成长。
这里会显示最新的几篇文章摘要。
在一个神秘的王国里,有一位伟大的勇者正在寻找他的最佳战斗伙伴。王国里有n个勇士,每个勇士的战斗力值记为ai。勇者决定通过一场淘汰赛来选择最终的战斗伙伴,比赛规则如下:
竞技场将进行n-1轮投票淘汰,每轮淘汰一个勇士。
在每一轮中,第i个勇士会将自己的一票投给与自己战斗力值差距最大的勇士,即找到j,使得|ai-aj|最大。此轮得票最多的勇士将被淘汰。
如果有多个勇士得票相同,战斗力值较大的勇士优先被淘汰。
如果第i个勇士在本轮中有多个差距相同的候选目标,他会优先投票给战斗力值较大的勇士。
勇者想知道,在所有轮次结束后,剩下的勇士是谁。
保证所有勇士战力值不同
第一行包含一个整数n,表示有n个勇士。
第二行包含n个整数,第i个整数ai表示第i个勇士的战斗力值。
输出一行一个整数,表示最终剩下的勇士的编号。
5
2 3 6 1 10
4
对于30%的数据,满足 n≤20,0≤ai≤1000
对于50%的数据,满足n≤5000,0≤ai≤10^5
对于100%的数据,满足n≤10,-109≤ai≤109
从直观上我们应该选择数据稀疏的一边的边界淘汰掉,怎么刻画数据的稀疏呢?我们可以想到,边界之间的值一个界点,分界点左边离右边边界远,全投给右边,左边类似,那么怎么精确刻画呢?对于v[0]和v[n-1],如果<=(v[0]+v[n-1])/2的数据数量更多,那么右边界值应该淘汰,如果两边一样多,也舍弃右边界值,反之,淘汰左边界值,那么只要重复到只有最后一个值就可以了,那么可以使用双指针,使用upper_bound()求区间大于中间值的索引,然后算两边的数量。
我的错误:1)搞错lower_bound()的功能,是求大于等于的值 2)求数量上搞错计算的边界
#include <bits/stdc++.h>
#include <iostream>
#define de(x) cout << #x << " = " << (x) << endl;
#define de2(x,y) cout << #x << " = " << (x) << " " << #y << " = " << (y) << endl;
#define de3(x,y,z) cout << #x << " = " << (x) << " " << #y << " = " << (y )<< " " << #z << " = " << (z) << endl;
#define f(i,a,b) for(int i = a;i < b;++i)
#define fd(i,a,b) for(int i = a;i >= b;--i)
#define fro for
#define mem(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
#define int long long
struct cow {
int id,val;
bool operator < (const cow a) const {
return val < a.val;
}
bool operator > (const cow a) const {
return val > a.val;
}
};
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
//
// freopen("E:/Code/C++/untitled1/input.txt","r",stdin);
// freopen("output.txt","w",stdout);
int n;
cin >> n;
vector<cow> v(n);
for (int i = 0;i < n;++i) cin >> v[i].val,v[i].id= i+1;
sort(v.begin(),v.end());
int l = 0,r = n-1;
while (l < r) {
cow mid;mid.val = v[l].val+v[r].val>>1;
int nub = upper_bound(v.begin()+l,v.begin()+r,mid) - (v.begin()); //算真正的索引,不是相对的
if ((nub-l)>=r-nub+1) r--; //使用实例测试一下怎么算的
else l++;
}
cout << v[r].id;
}