zoukankan      html  css  js  c++  java
  • CF891B-Gluttony【构造】

    正题

    题目链接:https://www.luogu.com.cn/problem/CF891B


    题目大意

    给出(n)个数字互不相同的一个序列(a),求它的一个排列(b),使得选出任意一个(1sim n)的下标真子集,都有(a)的对应下标和不等于(b)的对应下标和。

    (1leq nleq 22,0leq a_ileq 10^9)


    解题思路

    首先考虑对于每个(a_i)向它对应(b_i)连边,然后如果连出来的不是一个大小为(n)的环的话显然是错的,因为一次选择相当于选择环上的一条边,那么选一个环显然是对的。

    然后现在问题就变成了找一个环排列满足以上的条件,再考虑怎么找这个环排列,发现对应环上选择的连续一段那么最后肯定是头(+)而且尾(-),然后中间的不计贡献,换句话就是无法在这个环上选出一个子序列,然后(+/-)交错使得和为(0)

    对于这个问题的构造就很简单了,直接选择一个递增的序列,这样每个(+)肯定有个比他更大/小的(-)与它抵消。

    不过这样看上去其实是想复杂了,换种想法其实就是对于每个选出的除了最大的(a_i)都有一个更大的(b_i)对应,然后如果选择了最大的(a_i)那么这个差值需要选择另外(n-1)个才能抵上。

    时间复杂度:(O(nlog n))


    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;
    }
    
  • 相关阅读:
    文件操作
    验证进程 及jion方法
    进程笔记
    网络通信名词总结
    网络QQ聊天代码实例
    网络通信 粘包和 缓冲器
    udp
    UVALive 3983 Robotruck (单调队列,dp)
    UVA 10891 Game of Sum (决策优化)
    Uva 10635 Prince and Princess (LCS变形LIS)
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15325455.html
Copyright © 2011-2022 走看看