题目链接

大型补档计划

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

关键是发现无论怎样括号嵌套,每个元素始终只有对答案的贡献为 + 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\n", i - (cnt++) - 1);
for (int i = n; i > 1; i--) if (ans[i] == -1) puts("1");
return 0;
}

最新文章

  1. Intellj IDEA Java随笔
  2. angular+ionic返回上一页并刷新
  3. C#点击按钮用DataGridView动态增加行、删除行,增加按钮列
  4. POJ 2236 (简单并查集) Wireless Network
  5. ASP.NET缓存全解析6:数据库缓存依赖 转自网络原文作者李天平
  6. android的R.java
  7. OC基础 NSDate
  8. windows中.msc文件详解
  9. 8.docker的安全性
  10. 了解UI Automator Viewer
  11. 《javascript经典入门》-day01
  12. 使用VSTS的Git进行版本控制(一)——复制现有仓库
  13. Uninstall registry
  14. WebService的讲解 和 CXF 的初步使用
  15. Windows 2012 IIS ASP.NET 安装
  16. Linus运行jar包的操作
  17. 20155234 Exp2 后门原理与实践
  18. Percona-mysql server 5.5升级5.6
  19. Python之并发编程-协程
  20. poj----2155 Matrix(二维树状数组第二类)

热门文章

  1. tcp 客户端 synack的接收 以及 相互connect
  2. linux全局和个人配置文件说明
  3. xpth定位元素
  4. 回溯算法 - n 皇后问题
  5. 如何防范CSRF攻击
  6. webug第二关:从图片中你能找到什么?
  7. 一文带你读懂!华为云在ACMUG技术沙龙上都透露了些啥?
  8. Springboot整合163邮箱部署项目时发送不了邮件的解决方案
  9. MySQL开发篇(未完待续)
  10. api4excel - 接口自动化测试excel篇