Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) F. Double Knapsack

F. Double Knapsack
time limit per test
2.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given two multisets A and B. Each multiset has exactly n integers each between 1 and n inclusive. Multisets may contain multiple copies of the same number.

You would like to find a nonempty subset of A and a nonempty subset of B such that the sum of elements in these subsets are equal. Subsets are also multisets, i.e. they can contain elements with equal values.

If no solution exists, print  - 1. Otherwise, print the indices of elements in any such subsets of A and B that have the same sum.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 1 000 000) — the size of both multisets.

The second line contains n integers, denoting the elements of A. Each element will be between 1 and n inclusive.

The third line contains n integers, denoting the elements of B. Each element will be between 1 and n inclusive.

Output

If there is no solution, print a single integer  - 1. Otherwise, your solution should be printed on four lines.

The first line should contain a single integer ka, the size of the corresponding subset of A. The second line should contain ka distinct integers, the indices of the subset of A.

The third line should contain a single integer kb, the size of the corresponding subset of B. The fourth line should contain kb distinct integers, the indices of the subset of B.

Elements in both sets are numbered from 1 to n. If there are multiple possible solutions, print any of them.

Examples
Input
10
10 10 10 10 10 10 10 10 10 10
10 9 8 7 6 5 4 3 2 1
Output
1
2
3
5 8 10
Input
5
4 4 3 3 3
2 2 2 2 5
Output
2
2 3
2
3 5

【参考blog】http://blog.csdn.net/lwt36/article/details/50614772

【题意】给定2个N≤106元素的multiset,元素取值范围为1∼N。现在各从中选出一些元素的subset,subset也是multiset,使得他们的和相等。有解输出各自的大小以及下标,无解输出−1

【分析&&解题思路】参加上面blog,我也不写了,直接放代码吧。

【AC 代码】数据较多,上了读入挂。

//
//Created by just_sort 2016/9/9 18:40
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6+10;
int n,a[maxn],b[maxn];
struct FastIO
{
    static const int S = 1310720;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) return -1;
        return buf[pos ++];
    }
    inline int xuint()
    {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos ++] = x;
    }
    inline void wint(LL x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n ++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
int main()
{
    LL sum1,sum2;
    bool ok=0;
    n = io.xint();
    sum1 = sum2 = 0;
    for(int i=1; i<=n; i++) a[i] = io.xint();
    for(int i=1; i<=n; i++) b[i] = io.xint();
    for(int i=1; i<=n; i++) sum1 += a[i];
    for(int i=1; i<=n; i++) sum2 += b[i];
    //cout<<sum1<<" "<<sum2<<endl;
    if(sum1>sum2) swap(a,b) , ok = 1;
    vector<pair<int,int> >vs(n);
    vector<int>ans1;
    vector<int>ans2;
    for(auto &x : vs) x = {-1,-1};
    vs[0] = {1,1};
    LL xs = 0, ys = 0;
    for(int i = 1,j = 1; i <= n; ){
        xs += a[i++];
        while(j<=n && ys+b[j] <= xs) ys += b[j++];
        int dif = xs - ys;
        if(~vs[dif].first)
        {
            for(int k = vs[dif].first; k<i; k++) ans1.push_back(k);
            for(int k = vs[dif].second; k<j; k++) ans2.push_back(k);
            break;
        }
        vs[dif] = {i,j};
    }
    if(ok) swap(ans1,ans2);
    printf("%d\n",ans1.size());
    for(int i=0; i<ans1.size(); i++){
        printf("%d%c",ans1[i]," \n"[i==ans1.size()-1]);
    }
    printf("%d\n",ans2.size());
    for(int i=0; i<ans2.size(); i++){
        printf("%d%c",ans2[i]," \n"[i==ans2.size()-1]);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值