传送门


首先,选取子集的限制太宽了,子集似乎只能枚举,不是很好做。考虑加强限制条件:将“选取子集”的限制变为“选取子序列”的限制。在接下来的讨论中我们将会知道:将限制控制得更紧,问题也一定会有解。

现在我们需要求\(A,B\)的两个子序列,满足两者的和相等。显然可以前缀和,然后就不会做了qwq

考虑下面的算法:假定\(\sum\limits_{a \in A} a < \sum\limits_{b \in B} b\)(如果相等直接全选),设序列\(A\)前缀和为\(sumA_i\),序列\(B\)前缀和为\(sumB_i\)。

对于\(n+1\)个\(sumA_i\),在\(sumB\)中找到最小的大于等于它的元素\(sumB_j\),那么一定有\(sumB_j - sumA_i \in [0,n)\),可能的\(sumB - sumA\)有\(n\)种,但是有\(n+1\)组\(i,j\)。

根据抽屉原理,一定会存在两组\((i_1,j_1)(i_2,j_2)(i_1 > i_2)\)满足\(sumB_{j_1} - sumA_{i_1} = sumB_{j_2} - sumA_{i_2}\),即\(sumB_{j_1} - sumB_{j_2} = sumA_{i_1} - sumA_{i_2}\)。这样我们就找到了一组可行解:在\(A\)中选择\(A_x , x \in (i_2 , i_1]\),在\(B\)中选择\(B_y , y \in (j_2 , j_1]\)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<cmath>
#include<random>
//This code is written by Itst
using namespace std; inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
} #define PII pair < int , int >
#define st first
#define nd second
#define ll long long
const int MAXN = 1e6 + 7;
ll A[MAXN] , B[MAXN];
PII pos[MAXN]; signed main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
int N = read();
for(int i = 1 ; i <= N ; ++i)
A[i] = A[i - 1] + read();
for(int i = 1 ; i <= N ; ++i)
B[i] = B[i - 1] + read();
bool f = A[N] > B[N];
if(f) swap(A , B);
fill(pos , pos + N + 1 , PII(-1 , -1));
int p = 0;
for(int i = 0 ; i <= N ; ++i){
while(B[p] < A[i]) ++p;
if(pos[B[p] - A[i]] != PII(-1 , -1)){
PII t = pos[B[p] - A[i]];
if(!f){
printf("%d\n" , i - t.first);
for(int j = t.first + 1 ; j <= i ; ++j)
printf("%d " , j);
printf("\n%d\n" , p - t.second);
for(int j = t.second + 1 ; j <= p ; ++j)
printf("%d " , j);
}
else{
printf("%d\n" , p - t.second);
for(int j = t.second + 1 ; j <= p ; ++j)
printf("%d " , j);
printf("\n%d\n" , i - t.first);
for(int j = t.first + 1 ; j <= i ; ++j)
printf("%d " , j);
}
return 0;
}
else pos[B[p] - A[i]] = PII(i , p);
}
puts("-1");
return 0;
}

CF618F Double Knapsack 构造、抽屉原理的更多相关文章

  1. 2018.09.27 codeforces618F. Double Knapsack(抽屉原理+构造)

    传送门 思维题. 考虑维护两个数列的前缀和a1,a2,a3,...,ana_1,a_2,a_3,...,a_na1​,a2​,a3​,...,an​和b1,b2,b3,...,bnb_1,b_2,b_ ...

  2. Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) F. Double Knapsack 鸽巢原理 构造

    F. Double Knapsack 题目连接: http://www.codeforces.com/contest/618/problem/F Description You are given t ...

  3. Codeforces.618F.Double Knapsack(构造 鸽巢原理)

    题目链接 \(Description\) 给定两个大小为\(n\)的可重集合\(A,B\),集合中的元素都在\([1,n]\)内.你需要从这两个集合中各选一个非空子集,使它们的和相等.输出方案. \( ...

  4. CF618F Double Knapsack

    题意简化 给定两个大小为 n 的集合A,B,要求在每个集合中选出一个子集,使得两个选出来的子集元素和相等 元素范围在 1~n ,n<=1e5 题目连接 题解 考虑前缀和 令A集合的前缀和为SA, ...

  5. 【CF618F】Double Knapsack(构造)

    [CF618F]Double Knapsack(构造) 题面 洛谷 Codeforces 题解 很妙的一道题. 发现找两个数集很不爽,我们强制加强限制,我们来找两个区间,使得他们的区间和相等. 把区间 ...

  6. [codeforces 618 F] Double Knapsack (抽屉原理)

    题目链接:http://codeforces.com/contest/618/problem/F 题目: 题目大意: 有两个大小为 N 的可重集 A, B, 每个元素都在 1 到 N 之间. 分别找出 ...

  7. 51nod 1103 N的倍数(抽屉原理)

    1103 N的倍数 题目来源: Ural 1302 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍 ...

  8. POJ2356 Find a multiple 抽屉原理(鸽巢原理)

    题意:给你N个数,从中取出任意个数的数 使得他们的和 是 N的倍数: 在鸽巢原理的介绍里面,有例题介绍:设a1,a2,a3,……am是正整数的序列,试证明至少存在正数k和l,1<=k<=l ...

  9. 华农oj Problem J: 幻化【贪心/抽屉原理】

    Problem J: 幻化 Time Limit: 2 Sec Memory Limit: 128 MB Submit: 18 Solved: 3 [Submit][Status][Web Board ...

随机推荐

  1. 从0到1,了解NLP中的文本相似度

    本文由云+社区发表 作者:netkiddy 导语 AI在2018年应该是互联网界最火的名词,没有之一.时间来到了9102年,也是项目相关,涉及到了一些AI写作相关的功能,为客户生成一些素材文章.但是, ...

  2. mysql数据库备份并且实现远程复制

    一.实现ssh 远程登陆 机器环境: 192.167.33.108 clent 用户:crawler 192.167.33.77 server 用户:crawler 1.客户端 生成密钥 /home/ ...

  3. 强大的jupyter,python开发者的福音

    jupyter是一种交互式计算和开发环境的笔记,ipython命令行比原生的python命令行更加友好和高效,还可以运行web版的界面,支持多语言,输出图形.音频.视频等功能. 一.安装 pip3 i ...

  4. Linux基础命令第二天

    1,修改命令提示符 修改Linux命令行显示,需要用到PS1变量,PS1是Linux终端用户的一个环境变量.在终端输入命令:set,就会找到PS1变量,然后给PS1重新赋值,就会得到对应的样式. 默认 ...

  5. 跨站点请求伪造(CSRF)学习

    一.CSRF介绍 伪造一个站点,在站点中伪造一个向其他站点的请求,在用户访问该站点时让用户执行 假设有如下URL能删除一篇文章: 攻击者在自己的域中构造一个页面: 内容为: 使用一个img标签,其地址 ...

  6. [转]Gitlab-CI持续集成之Runner配置和CI脚本

    本文转自:https://www.cnblogs.com/jiukun/p/7481287.html 一.简介 1. 为实现持续集成,需为该项目准备以下两样东西: 1)软件集成脚本.(gitlab-c ...

  7. 关于HTTP中GET与POST的区别

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 看似很简单,其实是一道送命题 “标准答案”: GET在浏览器回退时是无害的,而POST会再次提交请求. ...

  8. 广州.NET微软技术俱乐部 微信群有用信息集锦

    考虑到广州.NET微软技术俱乐部 微信群 十分活跃. 有用信息很有可能被淹没. 所以建立此贴. 首先群的活跃是十分重要的. 所以我是不可能把群搞得像技术论坛和github一样, 因为微信群的定位我在& ...

  9. Vue一个案例引发「内容分发slot」的最全总结

    今天我们继续来说说 Vue,目前一直在自学 Vue 然后也开始做一个项目实战,我一直认为在实战中去发现问题然后解决问题的学习方式是最好的,所以我在学习一些 Vue 的理论之后,就开始自己利用业余时间做 ...

  10. WPF开源项目

    WPF有很多优秀的开源项目,我以为大家都知道,结果,问了很多人,其实他们不知道.唉,太可惜了! 先介绍两个比较牛逼的界面库 1.MaterialDesignInXamlToolkit Android风 ...