链接: https://ac.nowcoder.com/acm/contest/946/C
题面:
现在有n(n+1)个人想要分封诸侯,但是为了捍卫武王的至尊权威,最多只能建立2n个诸侯国。因此,周武王让这些人排成一排,从这些人中移去n(n-1)名,使得剩下的人数刚好为2n。
每个人都有一个威望,且不同人的威望各不相同。为了避免某个诸侯国国力过于强大而发生叛乱,动摇自己的统治地位,武王想要使各诸侯国的国力能够互相牵制,让剩下的人满足:威望最高的与威望次高的人相邻,威望第三高的与威望第四高的人相邻,……,威望次低的与威望最低的人相邻。
作为武王的亲信,为了不让武王发怒而遭杀身之祸,筱玛主动请缨,接下了这个难题。请你帮助筱玛,告诉武王是否存在这样的方案,若存在,则求出应该将哪些人留下。
1
≤
n
≤
1000
,
1
≤
n
≤
1000
,
1
≤
a
i
≤
1
0
9
1
≤
a
i
≤
1
0
9
。
1\le n\le1000,1≤n≤1000,1\le a_i\le10^91≤a i ≤10^9 。
1≤n≤1000,1≤n≤1000,1≤ai≤1091≤ai≤109。
思路:
一个结论是方案一定存在,且一定存在一种方案使得可以将这些人按顺序分成n组,每组n+1人,使得从每组选两个人配对,连起来构成一个合法方案。
具体证明:
所以我们可以将原始数组编号为0~n(n+1)-1,第i人属于第i/(n+1)组,然后从排序后威望的开始枚举前(n+1)高的有哪两个是属于同一组的,且该组进行标记,不在进入,找到后继续找接下来[n+2,2n+2]高的有哪两个属于同一组,直到2n个都被找到
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+2005;
struct node
{
int x,id;
}a[N];
vector<int>ans;
int flag[1005];
int vis[1005];
bool cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
int n,nn;
scanf("%d",&n);
nn=n;
n=n*(n+1);
for(int i=0;i<n;i++){
scanf("%d",&a[i].x);
a[i].id=i;
}
sort(a,a+n,cmp);
memset(flag,-1,sizeof flag);
for(int i=0;i<n;i++)
{
int x=a[i].id;
int bel=x/(nn+1);
if(vis[bel])
continue;
if(flag[bel]==-1){
flag[bel]=x;
continue;
}
ans.push_back(x);
ans.push_back(flag[bel]);
vis[bel]=1;
memset(flag,-1,sizeof flag);
}
for(auto it:ans)
cout<<it+1<<' ';
cout<<endl;
return 0;
}