原题
题目大意
给定两个多重集
A
和
Size(A)=Size(B)=n≤106
,且集合里的元素
ai,bi≤n
求
A
和
解题思路
令
∑ai≤∑bi
.
我们把数列转化为数列,计
fi=∑ij=1aj,gi=∑ij=1bi
,对于每一个
fi
,找一个最大的
gj
使得
gj≤fi
,则
fi−gj∈[0,n−1]
,考虑
f0
,则共有
n+1
个取值,而集合里面只有
n
个数。根据鸽笼原理(抽屉原理),一定有
∴fi1−fi2=gj1−gj2
.
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 1000005
#define ll long long
using namespace std;
ll sum1[maxn],sum2[maxn];
int a[maxn][2];
int n,ans1,ans2,ans3,ans4;
bool ok;
int read(){
int ret=0,ff=1;
char ch=getchar();
while (ch<'0' || ch>'9') {
if (ch=='-') ff=-1;
ch=getchar();
}
while (ch>='0' && ch<='9') {
ret=ret*10+ch-'0';
ch=getchar();
}
return ret*ff;
}
int main(){
n=read();
fo(i,1,n) {
a[i-1][0]=a[i-1][1]=-1;
sum1[i]=read();
sum1[i]+=sum1[i-1];
}
fo(i,1,n) {
sum2[i]=read();
sum2[i]+=sum2[i-1];
}
a[0][0]=0;
a[0][1]=0;
int last=0;
fo(i,1,n) {
while (sum1[i]-sum2[last]>=n && last<=n) last++;
if (last>n) continue;
if (a[sum1[i]-sum2[last]][0]==-1) {
a[sum1[i]-sum2[last]][0]=i;
a[sum1[i]-sum2[last]][1]=last;
}
else {
ok=1;
ans1=a[sum1[i]-sum2[last]][0];
ans2=i;
ans3=a[sum1[i]-sum2[last]][1];
ans4=last;
break;
}
while (sum1[i]-sum2[last+1]>=0 && last<=n-1) {
last++;
if (a[sum1[i]-sum2[last]][0]==-1) {
a[sum1[i]-sum2[last]][0]=i;
a[sum1[i]-sum2[last]][1]=last;
}
else {
ok=1;
ans1=a[sum1[i]-sum2[last]][0];
ans2=i;
ans3=a[sum1[i]-sum2[last]][1];
ans4=last;
break;
}
if (ok) break;
}
if (ok) break;
}
if (ans4==0) {
puts("-1");
return 0;
}
printf("%d\n",ans2-ans1);
fo(i,ans1+1,ans2) printf("%d ",i);
puts("");
printf("%d\n",ans4-ans3);
fo(i,ans3+1,ans4) printf("%d ",i);
return 0;
}