• AcWing 316 .减操作


    题目链接

    大型补档计划

    没想出来去看题解了。。。

    关键是发现无论怎样括号嵌套,每个元素始终只有对答案的贡献为 + a[i] 或者 - a[i]。

    而且第一个必然贡献是 +1, 第二个必然是 -1。

    所以用背包跑出来每个元素应该加还是减。

    然后就是构造了。

    观察到每个减操作实际上是把一个位置的贡献取反,而且这个位置不能是第一个位置。

    随便来一个贡献序列

    1 -1 1 1 -1 -1 1 -1 1 1 -1

    最后一步一定是 a[1] - a[2], 所以此时的 a[2] 里的正负性一定和我们求出来的相反,所以就可以把每个 1 都减掉(除了 a[1]),最后变成了这种形式:

    1 -1 -1 -1 -1 -1
    这时候用 a[1] 把后面都减掉,之前被减掉的别的 1 相当于取反了两次,贡献是对的。

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 101, S = 10005 * 2, P = 10000;
    int n, t, a[N], f[N][S], ans[N];
    int main() {
    	scanf("%d%d", &n, &t);
    	for (int i = 1; i <= n; i++) scanf("%d", a + i);
    	f[2][P + a[1] - a[2]] = -1;
    	for (int i = 3; i <= n; i++) 
    		for (int j = 0; j < S; j++) 
    			if (f[i - 1][j]) {
    				if(j + a[i] < S) f[i][j + a[i]] = 1;
    				if(j - a[i] >= 0 )f[i][j - a[i]] = -1;
    			}
    	int s = t + P;
    	for (int i = n; i > 1; i--) {
    		if((ans[i] = f[i][s]) == 1) s -= a[i];
    		else s += a[i]; 
    	}
    	int cnt = 0;
    	for (int i = 2; i <= n; i++) if (ans[i] == 1) printf("%d
    ", i - (cnt++) - 1);
        for (int i = n; i > 1; i--) if (ans[i] == -1) puts("1");
    	return 0;
    }
    
  • 相关阅读:
    nginx反向代理编译异常
    TCP/ip协议栈之内核调优
    Tcp之异常
    Codeforces Round #584
    Codeforces Round #588 (Div. 2)
    Codeforces Round #587 (Div. 3) F
    P4587 [FJOI2016]神秘数 主席树
    P4559 [JSOI2018]列队 主席树
    P4098 [HEOI2013]ALO 可持久化01trie
    4771: 七彩树 主席树
  • 原文地址:https://www.cnblogs.com/dmoransky/p/12380317.html
Copyright © 2020-2023  润新知