@ZCDHJ
2019-10-31T12:01:30.000000Z
字数 1504
阅读 430
未分类
很妙的一道题。
考虑加强限制,将子集变为连续子序列。假设 ,那么对于任意一个 的前缀和 都能找到一个最小的 ,此时因为数字的值域是 ,一定有 ,因为有 个 而值域里只有 个数字,根据鸽巢原理一定能找到一组 ,满足 ,移项得 也就是题目要求的序列。
#include <iostream>
#include <cstdio>
#include <cstring>
typedef long long LL;
const int MAXN = 1e6;
int n;
int pos[2][MAXN | 1];
LL a[MAXN | 1], b[MAXN | 1];
inline int read() {
register int x = 0;
register char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
int main() {
freopen("code.in", "r", stdin);
freopen("code.out", "w", stdout);
n = read();
for (int i = 1; i <= n; ++i) {
a[i] = a[i - 1] + read();
// printf("i=%d a[i]=%d b[i]=%d\n", i, a[i], b[i]);
}
for (int i = 1; i <= n; ++i) {
b[i] = b[i - 1] + read();
}
bool flag = false;
if (a[n] > b[n]) std::swap(a, b), flag = true;
memset(pos, -1, sizeof(pos));
pos[0][0] = 0;
pos[1][0] = 0;
for (int i = 1, p = 0; i <= n; ++i) {
while (b[p] < a[i]) ++p;
if (pos[0][b[p] - a[i]] != -1) {
if (flag == false) {
printf("%d\n", i - pos[0][b[p] - a[i]]);
for (int j = pos[0][b[p] - a[i]] + 1; j <= i; ++j) printf("%d ", j);
printf("\n");
printf("%d\n", p - pos[1][b[p] - a[i]]);
for (int j = pos[1][b[p] - a[i]] + 1; j <= p; ++j) printf("%d ", j);
printf("\n");
} else {
printf("%d\n", p - pos[1][b[p] - a[i]]);
for (int j = pos[1][b[p] - a[i]] + 1; j <= p; ++j) printf("%d ", j);
printf("\n");
printf("%d\n", i - pos[0][b[p] - a[i]]);
for (int j = pos[0][b[p] - a[i]] + 1; j <= i; ++j) printf("%d ", j);
printf("\n");
}
return 0;
}
pos[0][b[p] - a[i]] = i;
pos[1][b[p] - a[i]] = p;
}
return 0;
}