Purple Book Exercise 8-10 UVa 1614 (Greedy + Conclusion)

I pondered this question for an hour, trying to beat sum/2 with a backpack, and found that the data was too large to store in the space.

Then I finally went to someone else's blog and found that there was a magical conclusion...

Fortunately, I didn't delve into it any more, I feel that this conclusion must be unexpected...

The conclusion is: when 1 <= a[i] <= i, the first i numbers must be able to make up all the integers from 1~sum[i]

See this for proof https://blog.csdn.net/wcr1996/article/details/43957461

When other bloggers have written this conclusion, just sort them, from big to small, add up to sum/2, if you can make it up, you can make it up in the end.

But I have been unable to figure out why it must be possible to make it up like this, why should it be sorted? ? Other blogs don't seem to have

give an explanation...

Then I thought about it for a long time and figured it out.

First of all, this conclusion proves that it can be beat into sum/2 (sum is an odd number regardless, output No)

Then, sort from largest to smallest.

Assuming that the first number that can be made up is a[k], a[k] is obviously the first number less than or equal to sum/2

That is to say, the numbers before a[k], that is, all numbers greater than a[k], are greater than sum/2

That is to say, it is impossible for these numbers to beat sum/2.

Then sum/2 subtracts a[k]. Then the number after a[k] must be sum/2-a[k];

why? Here is the key.

Because the numbers to add sum/2-a[k] must be less than sum/2-a[k], and these numbers must be after a[k]

Because a[k] is the first number less than or equal to sum/2, then the first number less than or equal to sum/2-a[k]

It must be less than or equal to a[k], and it must be behind a[k].

Therefore, the numbers to make up sum/2-a[k] are all after a[k], and these numbers have not been selected.

Because the conclusion at the beginning shows that sum/2-a[k] can definitely be summed up , and all needs to be summed up

The number of sum/2-a[k] has not been traversed yet.

Therefore, sum/2-a[k] must be made up of numbers that have not been traversed yet.

And so on, keep doing it, you can definitely get it done

over!!!!!!!!!!


#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;

const int MAXN = 112345;
int a[MAXN], id[MAXN], n;

bool cmp(int x, int y)
{
	return a[x] > a[y];
}

intmain()
{
	while(~scanf("%d", &n))
	{
		long long sum = 0;
		REP(i, 0, n)
		{
			scanf("%d", &a[i]);
			sum += a[i];
			id[i] = i;
		}
		if(sum & 1) { puts("No"); continue;	}
		
		sort(id, id + n, cmp);
		sum >>= 1;
		
		REP(i, 0, n)
		{
			int t = id[i];
			if(a[t] <= sum)
			{
				sum -= a[t];
				a[t] = 1;
			}
			else a[t] = -1;
		}
		
		puts("Yes");
		REP(i, 0, n) printf("%d ", a[i]);
		puts("");
	}

	return 0;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326007574&siteId=291194637