标签:Gluttony 环上 22 int CF891B 构造 leq ai include
正题
题目链接:https://www.luogu.com.cn/problem/CF891B
题目大意
给出 n n n个数字互不相同的一个序列 a a a,求它的一个排列 b b b,使得选出任意一个 1 ∼ n 1\sim n 1∼n的下标真子集,都有 a a a的对应下标和不等于 b b b的对应下标和。
1 ≤ n ≤ 22 , 0 ≤ a i ≤ 1 0 9 1\leq n\leq 22,0\leq a_i\leq 10^9 1≤n≤22,0≤ai≤109
解题思路
首先考虑对于每个 a i a_i ai向它对应 b i b_i bi连边,然后如果连出来的不是一个大小为 n n n的环的话显然是错的,因为一次选择相当于选择环上的一条边,那么选一个环显然是对的。
然后现在问题就变成了找一个环排列满足以上的条件,再考虑怎么找这个环排列,发现对应环上选择的连续一段那么最后肯定是头 + + +而且尾 − - −,然后中间的不计贡献,换句话就是无法在这个环上选出一个子序列,然后 + / − +/- +/−交错使得和为 0 0 0。
对于这个问题的构造就很简单了,直接选择一个递增的序列,这样每个 + + +肯定有个比他更大/小的 − - −与它抵消。
不过这样看上去其实是想复杂了,换种想法其实就是对于每个选出的除了最大的 a i a_i ai都有一个更大的 b i b_i bi对应,然后如果选择了最大的 a i a_i ai那么这个差值需要选择另外 n − 1 n-1 n−1个才能抵上。
时间复杂度: O ( n log n ) O(n\log n) O(nlogn)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=30;
int n,a[N],b[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+1+n);
for(int i=1;i<=n;i++){
if(a[i]==b[n])printf("%d ",b[1]);
else printf("%d ",b[upper_bound(b+1,b+1+n,a[i])-b]);
}
return 0;
}
标签:Gluttony,环上,22,int,CF891B,构造,leq,ai,include 来源: https://blog.csdn.net/Mr_wuyongcong/article/details/120439954
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。