UVA 1614 - Hell on the Markets 奇怪的股市(贪心,结论)

先证明一个结论吧,对于1≤ai≤i+1,一定可以表示出1~sum[i]中的任意一个数.

对于i=1显然成立,

假设对于i=k结论成立,那么对于i=k+1来说,只要证明sum[k]+i,1≤i≤ak+1可以凑出来就行了。

因为sum[k]+i≥k+1,且1≤ak+1≤k+1,所以可以先选一个ak+1,剩下的0≤sum[k]+i-ak+1≤sum[k]一定是可以有前面的数字凑出来的。

这就证明了贪心的正确性。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;
int a[maxn];
int r[maxn];
bool cmp(int x,int y) { return a[x] < a[y]; }

int main()
{
    int n;
    while(~scanf("%d",&n)){
        long long sum = 0;
        for(int i = 0; i < n; i++) scanf("%d",a+i),sum += a[i],r[i] = i;
        if(sum&1) { puts("No"); continue; }
        sort(r,r+n,cmp);
        sum >>= 1;
        for(int i = n-1; i >= 0; i--){
            int j = r[i];
            if(a[j]<=sum){
                sum -= a[j];
                a[j] = 1;
            }else {
                a[j] = -1;
            }
        }
        printf("Yes\n%d",a[0]);
        for(int i = 1; i < n; i++) printf(" %d",a[i]);
        puts("");
    }
    return 0;
}
时间: 2024-12-13 08:23:22

UVA 1614 - Hell on the Markets 奇怪的股市(贪心,结论)的相关文章

Uva - 1614 - Hell on the Markets

Most financial institutions had become insolvent during financial crisis and went bankrupt or were bought by larger institutions, usually by banks. By the end of financial crisis of all the financial institutions only two banks still continue to oper

UVA - 1614 Hell on the Markets 贪心+推理

题目大意:给出n个数字,第i个数字的大小满足 1 <= ai <= i,要求确定每个数的正负号,使得所有数的总和为0 解题思路:总和为0,那sum % 2 == 0 接着分析一下,因为和为0,所以sum / 2要能通过这n个数得到,那就枚举看看能不能得到 从大到小枚举,取当前这个数的个数和(sum/当前这个数)的值的最小值,接着sum减去这个最小值乘于当前值 如果(sum/当前这个数)是取得的最小值,那么分两种情况 一种是能除尽的,那么(sum - 最小值 * 当前这个数)就刚好为0了,也就是

uva 10905 Children&#39;s Game(排序或者有点贪心)

今天配置vim没有成功,老是显示什么error,唉,其实之前成功过的,只不过是重装了dev,然后就变了,可能环境 变量的问题,但是我都改了的啊,以后再调吧... 这道题其实不是我想出来的看的题解,又看题解了...好吧,既然看了题解就得好好掌握才是.用到了我刚刚在 c++ primer里面学的string类,挺好用的,以后我准备写程序尽量用c++内容,多练练.. 又加深理解了qsort调用的cmp函数,它的两个参数其实都是要比较的元素的指针,比如这道题中的元素是string类 型,那么他们都是st

【uva 1614】Hell on the Markets(算法效率--贪心)

题意:有一个长度为N的序列A,满足1≤Ai≤i,每个数的正负号不知.请输出一种正负号的情况,使得所有数的和为0.(N≤100000) 解法:(我本来只想静静地继续做一个口胡选手...←_← 但是因为这题的贪心实在是太厉害了!我就单看,就盯了题解半小时以上...而代码又那么短,我就打了代码了...其实我又不太理解为什么一定要排序.) 贪心部分的理论依据:前i个数可以凑出1-sum[i]的所有整数. 证明:第二类数学归纳,n=1时成立,假设n=k之前所有项都成立,当n=k+1时.sum[k+1]=s

UVA - 1614 Hell on the Market(贪心)

Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Most financial institutions had become insolvent during financial crisis and went bankrupt or were bought by larger institutions, usually by banks. By

1614 - Hell on the Markets(贪心)

n很大,不能DP,令我不得不想到了贪心,结果贪心完了莫名其妙的AC.. 之后查找该题的证明,发现网上题解都不求甚解,只有一个博客给出了一个说法: 因为 1 <= a[i] <= i,可用数学归纳法证明,用 a[1]~a[i] 的部分或全部元素通过求和,一定可以凑出 1~sum[i] 的每个整数(sum[i]是前 i 个元素的和) 的确,1 <= a[i] <= i是个奇怪的限制条件,大家不妨记住这个奇妙的结论, 如果我以后得到证明方法会再回来补充 . 有了这个结论, 我们就可以贪心

UVa1614 Hell on the Markets (贪心,结论)

链接:http://bak.vjudge.net/problem/UVA-1614 分析:http://blog.csdn.net/wcr1996/article/details/43957461 有了这个结论,接下来就是贪心搞一搞了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 100000 + 5

UVA - 12545 Bits Equalizer (比特变换器)(贪心)

题意:输入两个等长(长度不超过100)的串S和T,其中S包含字符0,1,?,但T只包含0和1,你的任务是用尽量少的步数把S变成T.有以下3种操作: 1.把S中的0变成1. 2.把S中的"?"变成0或1. 3.交换S中任意两个字符. 分析: 1.为保证步数最少,先统计两串中1的个数和1的位置.如果cnta>cntb,则不能把S变成T,因为1不能变成0. 2.先将?变成0或1,变换原则是若cnta<cntb且b中对应位置为1,则变为1:否则,变为0. 3.再将0变成1,变换原则

UVA 11491 Erasing and Winning 奖品的价值 (贪心)

题意:给你一个n位整数,让你删掉d个数字,剩下的数字要尽量大. 题解:因为最后数字位数是确定的,而且低位数字对答案的贡献是一定不及高位数字的,所以优先选择选最大且最靠左边的数字,但是有一个限制,选完这个数字以后右边剩下的数字要保证足够接下来的选择,所以我想到了优先队列,记录一个信息,选的数字所在的位置,以及上一个数字所在的位置,如果当前出队的数字在上一个选的位置前面就直接丢掉,每次选完一个以后剩下要选的数字就减少了,满足限制的条件的数字会增加,再把新的待选数字加入队列. #include<bit