A. Avoiding Zero (prefix and + greedy) Codeforces Global Round 11

Link to the original question: https://codeforces.com/contest/1427/problem/A

Insert picture description here
Test sample

input
4
4
1 -2 3 -4
3
0 0 0
5
1 -1 1 -1 1
6
40 -31 -9 0 13 -40
output
YES
1 -2 3 -4
NO
YES
1 1 -1 1 -1
YES
-40 13 40 0 -9 -31

Note

Explanation of the first testcase: An array with the desired properties is b=[1,−2,3,−4]. For this array, it holds:

  • The first element of b is 1.
  • The sum of the first two elements of b is −1.
  • The sum of the first three elements of b is 2.
    The sum of the first four elements of b is −2.

Explanation of the second testcase: Since all values in a are 0, any rearrangement b of a will have all elements equal to 0 and therefore it clearly cannot satisfy the second property described in the statement (for example because b1=0). Hence in this case the answer is NO.

Explanation of the third testcase: An array with the desired properties is b=[1,1,−1,1,−1]. For this array, it holds:

  • The first element of b is 1.
  • The sum of the first two elements of b is 2.
  • The sum of the first three elements of b is 1.
  • The sum of the first four elements of b is 2.
  • The sum of the first five elements of b is 1.

Explanation of the fourth testcase: An array with the desired properties is b=[−40,13,40,0,−9,−31]. For this array, it holds:

  • The first element of b is −40.
  • The sum of the first two elements of b is −27.
  • The sum of the first three elements of b is 13.
  • The sum of the first four elements of b is 13.
  • The sum of the first five elements of b is 4.
  • The sum of the first six elements of b is −27.

Meaning: give you a length of nninteger sequence of n aaa , now you need to rearrange the sequence so that the prefix sum is not0 00 , if there is no such arrangement, output "NO".

Problem solving idea: we want to make all prefixes and pre prep r e is not0 00 , then how to deal with it? Forpre[i] pre[i]p r e [ i ] , other equations, etc.pre [i − 1] + a [i] pre [i-1] + a [i]pre[i1]+a [ i ] . So each prefix sum is actually related to the previous prefix sum,In other words, if I use an ans ansa n s traverse the arranged array once,ans ansa n s accumulates the sum of elements. Ifans=0 ans=0a n s=0 , then it is not feasible.Then according to the greedy principle, we have to make ans ≠ 0 ans≠0a n s=0 , we either always put positive numbers in front and then negative numbers, or we always put negative numbers in front and then positive numbers.(Note: 0 00 can be placed anywhere in the middle, it has no effect)At this time we found a wonderful thing. If the sum of positive numbers is equal to the sum of negative numbers, then it is impossible because the length is nnThe prefix sum of n must be0 00 , then are other conditions necessarily satisfied? The answer is yes, we must make the prefix sum not0 00 , then if the sum of positive numbers is greater than the sum of negative numbers, then we always put positive numbers first, and then put0 00 , and then put a negative number, it is equivalent to descending sort, so that the prefix sum is always greater than 0. If the sum of negative numbers is greater than the sum of positive numbers, then we will always put negative numbers first, and then put0 00 , and then put a positive number, it is equivalent to increasing sort, so that the prefix sum is always less than 0.

AC code

/*
*邮箱:[email protected]
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

int t,n;
int main(){
    
    
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>n;
			vector<int> num(n);
			int pos=0,neg=0;//pos统计正数和,neg统计负数和。一定要初始化。
			rep(i,0,n-1){
    
    
				cin>>num[i];
				if(num[i]>0){
    
    
					pos+=num[i];
				}
				else if(num[i]<0){
    
    
					neg+=num[i];
				}
			}
			//目的使得前缀和不为0,故要么前面全是正数使得和最大,再用负数去减。要么前面全是负数使得和最小,再用正数去加。
			if(pos+neg==0){
    
    
				//这种必不可能,无论你怎么排列,长度为n的前缀和必为0.
				cout<<"NO"<<endl;
			}
			//那么其他就可行。
			else if(pos+neg>0){
    
    
				//说明正数和大,先放正数,再放负数,必满足,我们直接从大到小排列即可。
				sort(num.begin(),num.end(),greater<int>() );
				cout<<"YES"<<endl;
				rep(i,0,n-1){
    
    
					cout<<num[i]<<" ";
				}
				cout<<endl;
			}
			else{
    
    
				//说明负数和大,先放负数,再放正数,必满足,我们直接从小到大排列即可。
				sort(num.begin(),num.end());
				cout<<"YES"<<endl;
				rep(i,0,n-1){
    
    
					cout<<num[i]<<" ";
				}
				cout<<endl;
			}
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/hzf0701/article/details/109007379