传送门


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

现在我们需要求\(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]\)。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<ctime>
  5. #include<cctype>
  6. #include<algorithm>
  7. #include<cstring>
  8. #include<iomanip>
  9. #include<queue>
  10. #include<map>
  11. #include<set>
  12. #include<bitset>
  13. #include<vector>
  14. #include<stack>
  15. #include<cmath>
  16. #include<random>
  17. //This code is written by Itst
  18. using namespace std;
  19. inline int read(){
  20. int a = 0;
  21. char c = getchar();
  22. bool f = 0;
  23. while(!isdigit(c) && c != EOF){
  24. if(c == '-')
  25. f = 1;
  26. c = getchar();
  27. }
  28. if(c == EOF)
  29. exit(0);
  30. while(isdigit(c)){
  31. a = a * 10 + c - 48;
  32. c = getchar();
  33. }
  34. return f ? -a : a;
  35. }
  36. #define PII pair < int , int >
  37. #define st first
  38. #define nd second
  39. #define ll long long
  40. const int MAXN = 1e6 + 7;
  41. ll A[MAXN] , B[MAXN];
  42. PII pos[MAXN];
  43. signed main(){
  44. #ifndef ONLINE_JUDGE
  45. freopen("in","r",stdin);
  46. //freopen("out","w",stdout);
  47. #endif
  48. int N = read();
  49. for(int i = 1 ; i <= N ; ++i)
  50. A[i] = A[i - 1] + read();
  51. for(int i = 1 ; i <= N ; ++i)
  52. B[i] = B[i - 1] + read();
  53. bool f = A[N] > B[N];
  54. if(f) swap(A , B);
  55. fill(pos , pos + N + 1 , PII(-1 , -1));
  56. int p = 0;
  57. for(int i = 0 ; i <= N ; ++i){
  58. while(B[p] < A[i]) ++p;
  59. if(pos[B[p] - A[i]] != PII(-1 , -1)){
  60. PII t = pos[B[p] - A[i]];
  61. if(!f){
  62. printf("%d\n" , i - t.first);
  63. for(int j = t.first + 1 ; j <= i ; ++j)
  64. printf("%d " , j);
  65. printf("\n%d\n" , p - t.second);
  66. for(int j = t.second + 1 ; j <= p ; ++j)
  67. printf("%d " , j);
  68. }
  69. else{
  70. printf("%d\n" , p - t.second);
  71. for(int j = t.second + 1 ; j <= p ; ++j)
  72. printf("%d " , j);
  73. printf("\n%d\n" , i - t.first);
  74. for(int j = t.first + 1 ; j <= i ; ++j)
  75. printf("%d " , j);
  76. }
  77. return 0;
  78. }
  79. else pos[B[p] - A[i]] = PII(i , p);
  80. }
  81. puts("-1");
  82. return 0;
  83. }

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. Spring Boot 2.x(九):遇到跨域不再慌

    什么是跨域 首先,我们需要了解一下一个URL是怎么组成的: // 协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址 http: + // + www.baidu.com + :8080/ ...

  2. 自动化运维工具fabric使用教程

    摘要:当需要同时管理许多服务器时,如果我们一台一台登陆上去操作会显得费时又费力.此时我们可以用fabric这个包提供的API来编写python脚本完成服务器集群的统一管理. 核心原理:fabric为主 ...

  3. C#杂记-自动实现的属性(自动属性)

    基础知识: 普通属性:可读或可写并将值存储到一个私有变量中的属性,不对数据做任何加工,没有自定义代码. private string name public string Name { get{ret ...

  4. Java开发笔记(十五)短路逻辑运算的优势

    前面提到逻辑运算只能操作布尔变量,这其实是不严谨的,因为经过Java编程实现,会发现“&”.“|”.“^”这几个逻辑符号竟然可以对数字进行运算.譬如下面的代码就直接对数字分别开展了“与”.“或 ...

  5. OO第一单元作业总结

    oo第一单元的作业是对多项式的求导.下面就是对三次作业分别进行分析. 第一次作业 分析 第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数 ...

  6. CentOS7.3 yum install MySQL5.7

    安装环境:阿里云服务器 + CentOS7.3 测试工具:Navicat for MySQL 参考博客:https://blog.csdn.net/qq_38417808/article/detail ...

  7. react 函数子组件(Function ad Child Component)

    今天学习了react中的函数子组件的概念,然后在工作中得到了实际应用,很开心,那么好记性不如烂笔头,开始喽~ 函数子组件(FaCC )与高阶组件做的事情很相似, 都是对原来的组件进行了加强,类似装饰者 ...

  8. 驰骋工作流引擎JFlow与activiti的对比之4种包含多实例的模式

    1. 无同步的多实例(MIwithout) 在流程中,一个活动可以激活多个实例,每个实例相互独立,并不需要在后面进行同步. 例子:比如用户购买了N本书,于是后续的支付账单.更新客户可以以本书为单位各自 ...

  9. 关于Windows系统不会变慢的设想

    记录软件安装的过程,比如创建了哪些服务,哪些计划任务以及启动项等等. 然后软件安装完成后把关于软件的进程,服务,计划任务等都删掉. 然后手动创建一个脚本,用脚本代替软件的启动.比如,如果要启动sqls ...

  10. 自定义HorizontalScrollView的scrollBar

    尊重劳动成果,转载请标明出处http://www.cnblogs.com/tangZH/p/8423803.html android滑动组件的scrollBar,看了不是很顺眼,没办法,因为项目需求, ...