CF618F Double Knapsack

题目

CF618F Double Knapsack

思路

很不错的一个构造题(我不会
考虑计两个数组\(A,B\)作为前缀和
\(j\)为满足\(A_i <= B_j\)且最小的值
由此得出:\(A_i > B_{j - 1}\)
再得出\(B_j - A_i <= n\)
\(i\)\(0\)开始计,所以以鸽笼原理,必有\(A_{i1} - B_{j1} = A{i2} - B_{j2}\)
于是移项 得出答案
然后就是一些细节上的处理

代码

// code by Dix_
#include<bits/stdc++.h>
#define ll long long

inline ll read(){
    char C=getchar();
    ll N=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
    return F*N;
}

ll n,a[1000010],b[1000010];
ll A[1000010],B[1000010];

struct P{
	ll x,y;
}QWQ[1000010];

ll num = 0;

ll lb = 0;

int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i){
		scanf("%lld",&a[i]);
		A[i] = A[i - 1] + a[i];
	}
	for(int i = 1;i <= n;++i){
		scanf("%lld",&b[i]);
		B[i] = B[i - 1] + b[i];
	}
	bool f = 0;
	if(B[n] < A[n]){
		f = 1;
		std::swap(A,B);
	}
	for(int i = 0;i <= n;++i)
	QWQ[i].x = -1,QWQ[i].y = -1;
	ll v;
	for(int i = 0;i <= n;++i){
		while(B[lb] < A[i] && lb + 1 <= n)
		lb += 1 ;
		v = B[lb] - A[i];
		if(QWQ[v].x == -1)
			QWQ[v].x = i,QWQ[v].y = lb;
		else{
			num = i;
			break;
		}
 	}
 	if(f)
 	std::swap(A,B),std::swap(num,lb),std::swap(QWQ[v].x,QWQ[v].y);
	std::cout<<num - QWQ[v].x<<std::endl;
	for(int i = QWQ[v].x + 1;i <= num;++i){
		std::cout<<i<<" ";
	}
	puts("");
	std::cout<<lb - QWQ[v].y<<std::endl;
	for(int i = QWQ[v].y + 1;i <= lb;++i){
		std::cout<<i<<" ";
	}
}

原文地址:https://www.cnblogs.com/dixiao/p/14447062.html