「CF618F」Double Knapsack 题解

只能说。。。

Description

给你两个可重集 \(A,B\)\(A,B\) 的元素个数都为 \(n\),它们中每个元素的大小 \(x\in [1,n]\)。请你分别找出 \(A,B\) 的子集,使得它们中的元素之和相等。\(n\leq 10^6\)

Solution

将找子集强化成找子段(不知道怎么想的),令 \(sa_{n}\) 表示 \(A\) 的前缀和,\(sb_{n}\) 表示 \(B\) 的前缀和,即找到点对 \((x_{1},y_{1}),(x_{2},y_{2})\),使得 \(sa_{x_{1}}-sa_{x_{2}}=sb_{y_{1}}-sb_{y_{2}}\)
我们让 \(sa_{n}\leq sb_{n}\),则对于每个 \(sa_{i}\),都可以找到一个 \(sb_{j}\geq sa_{i},sb_{j}-sa_{i}\in[0,n)\)。又因为 \(i\)\(n+1\) 种取值,则一定存在一组 \((i,j)\)\(sb_{j}-sa_{i}\) 重复,即得上述点对。

Code

#include <bits/stdc++.h>
using namespace std;

using ci = const int;

using u32 = uint32_t;
using i64 =  int64_t;
using u64 = uint64_t;

template<class T> inline void Max(T &x, const T &y) { if (x < y) x = y; }
template<class T> inline void Min(T &x, const T &y) { if (y < x) x = y; }

using pii = pair<int, int>;

const int N = 1e6 + 5;

int n, a[N], b[N];
bool vis[N];
pii tong[N];
i64 sa[N], sb[N];

void op(int l, int r) {
	cout << r - l + 1 << endl;
	for (int i = l; i <= r; ++i) cout << i << " ";
	cout << endl;
}
void output(int al, int ar, int bl, int br) {
	op(al, ar); op(bl, br);
}

void solve1() {
	int tp = 0;
	for (int i = 0, v; i <= n; ++i) {
		while (sb[tp] < sa[i]) ++tp;
		v = sb[tp] - sa[i];
		if (vis[v]) return output(tong[v].first + 1, i, tong[v].second + 1, tp);
		vis[v] = 1, tong[v] = { i, tp };
	}
}

void solve2() {
	int tp = 0;
	for (int i = 0, v; i <= n; ++i) {
		while (sa[tp] < sb[i]) ++tp;
		v = sa[tp] - sb[i];
		if (vis[v]) return output(tong[v].first + 1, tp, tong[v].second + 1, i);
		vis[v] = 1, tong[v] = { tp, i };
	}
}

int main() {
#ifndef ONLINE_JUDGE
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
#endif

	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	memset(tong, 0xff, sizeof tong);

	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];
	for (int i = 1; i <= n; ++i) cin >> b[i];

	for (int i = 1; i <= n; ++i) sa[i] = sa[i - 1] + a[i];
	for (int i = 1; i <= n; ++i) sb[i] = sb[i - 1] + b[i];

	if (sa[n] < sb[n]) solve1();
	else solve2();

	return 0;
}
posted @ 2025-01-22 11:43  cqbzljh  阅读(16)  评论(0)    收藏  举报