解题思路:
真是道非常妙的构造。
不妨设总和小的是集合A。
我们把集合看成数组,对两个数组各求前缀和(包括0号位置);
那么对于每个
sumA[i]
,必然存在一个
sumB[j]
,使得
0≤sumA[i]−sumB[i]<n
,设为
d[i]
,可以发现
j
随
注意到最后
d[i]
有
n+1
个
(d[0]到d[n])
,而
d[i]
只有
n
个取值
即存在:
sumA[i]−sumB[j]=sumA[i′]−sumB[j′]
(不妨设i>i′,那么j>j′)
移项得:
sumA[i]−sumA[i′]=sumB[j]−sumB[j′]
所以 A[i′+1]到A[i],B[j′+1]到B[j] 即为所求。
是不是很妙?
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=1000005;
int n,a[N],b[N],cnt1,cnt2,st1,ed1,st2,ed2,p[N],vis[N];
void solve(int a[],int b[])
{
memset(vis,-1,sizeof(vis));
int i=0,j=0,k,d;
for(i=0;i<=n;i++)
{
while(a[i]-b[j]>=n)j++;
p[i]=j,d=a[i]-b[j];
if(vis[d]==-1)vis[d]=i;
else
{
cnt1=i-vis[d],cnt2=j-p[vis[d]];
st1=vis[d]+1,ed1=i,st2=p[vis[d]]+1,ed2=j;
break;
}
}
}
int main()
{
//freopen("lx.in","r",stdin);
n=getint();
for(int i=1;i<=n;i++)a[i]=getint()+a[i-1];
for(int i=1;i<=n;i++)b[i]=getint()+b[i-1];
if(a[n]<=b[n])solve(a,b);
else solve(b,a),swap(cnt1,cnt2),swap(st1,st2),swap(ed1,ed2);
cout<<cnt1<<'\n';
for(int i=st1;i<=ed1;i++)cout<<i<<' ';
cout<<'\n';
cout<<cnt2<<'\n';
for(int i=st2;i<=ed2;i++)cout<<i<<' ';
return 0;
}