CF1427A Avoiding Zero 题解

Content

请将一个长度为 \(n\) 的数列 \(A\) 重新排序,使得这个数列所有的前缀和 \(\neq 0\),或者证明没有这样的方案。

数据范围:\(t\) 组数据,\(1\leqslant t\leqslant 1000\)\(1\leqslant n\leqslant 50\)\(-50\leqslant a_i\leqslant A_i\leqslant 50\)

Solution

不难发现,当且仅当所有数的和都为 \(0\) 的时候不存在满足题目要求的方案。

否则,将所有的正整数放进一起,将所有的负整数放在一起,然后分类讨论:

  • 如果所有正整数的和大于所有负整数的和的绝对值,那么我们就考虑先把所有的正整数放在前面,再把所有的负整数放在后面,这样可以保证前缀和不为 \(0\)
  • 否则,我们先把所有的负整数放在前面,再把所有的正整数放在后面。

至于如果存在 \(0\),那就放在在所有的非零数后面就行了。

想法略显复杂,但是实现起来也是不难的,对吧?

Code

int n, a[57], sum, sump, sumn, po[57], ne[57];

int main() {
    MT {
        n = Rint, sum = sump = sumn = 0;
        F(int, i, 0, n) po[i] = ne[i] = 0;
        F(int, i, 1, n) sum += (a[i] = Rint), sump += a[i] * (a[i] > 0), sumn += (-a[i]) * (a[i] < 0);
        if(!sum) {NO; continue;}
        YES;
        F(int, i, 1, n) if(a[i] > 0) po[++po[0]] = a[i]; else if(a[i] < 0) ne[++ne[0]] = a[i];
        if(sump > sumn) {F(int, i, 1, po[0]) print_space(po[i]); F(int, i, 1, ne[0]) print_space(ne[i]); F(int, i, 1, n - po[0] - ne[0]) printf("0 ");}
        else {F(int, i, 1, ne[0]) print_space(ne[i]); F(int, i, 1, po[0]) print_space(po[i]); F(int, i, 1, n - po[0] - ne[0]) printf("0 ");}
        puts("");
    }
    return 0;
}
posted @ 2021-12-15 22:18  Eason_AC  阅读(38)  评论(0)    收藏  举报