正题

题目链接:https://www.luogu.com.cn/problem/CF618F


题目大意

给出大小为\(n\),值域为\([1,n]\)的两个可重集合\(A,B\)

需要你对它们各求出可重子集使得两个子集中的数字和相等

输出方案。

\(1\leq n\le 10^6\)


解题思路

这个值域范围就很提示性的往鸽笼原理方面考虑。

此题的结论就是一定有连续子序列的解。

先搞一个前缀和\(A,B\),假设\(A_n\leq B_n\)。

现在我们要求两个\(l,r\)满足

\[A_{r_1}-A_{l_1}=B_{r_2}-B_{l_2}
\]
\[\Rightarrow A_{r_1}-B_{r_2}=A_{l_1}-B_{l_2}
\]

现在问题就变为了求两个相同的\(A_x-B_y\).

对于每个\(A_x\)(\(x\in[0,n]\)),求出一个最大的\(y\)使得\(B_y\leq A_x\)

那么显然有\(A_x-B_y\in[0,n-1]\),也就是\(A_x-B_y\)一共只有\(n\)种取值,而我们有\(n+1\)个,所以至少有两个相同的。

开两个桶记录一下出现位置就好了。

时间复杂度\(O(n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e6+10;
ll n,a[N],b[N],la[N],lb[N];
signed main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]),a[i]+=a[i-1];
for(ll i=1;i<=n;i++)
scanf("%lld",&b[i]),b[i]+=b[i-1];
bool f=0;
if(a[n]>b[n]){
for(ll i=1;i<=n;i++)
swap(a[i],b[i]);
f=1;
}
ll ala,alb,ara,arb;
for(ll i=0,j=0;i<=n;i++){
while(b[j]<=a[i])j++;j--;
if(la[a[i]-b[j]]){
ala=la[a[i]-b[j]];
alb=lb[a[i]-b[j]];
ara=i;arb=j;
}
la[a[i]-b[j]]=i+1;
lb[a[i]-b[j]]=j+1;
}
if(f)swap(ala,alb),swap(ara,arb);
printf("%lld\n",ara-ala+1);
for(ll i=ala;i<=ara;i++)printf("%lld ",i);
printf("\n%lld\n",arb-alb+1);
for(ll i=alb;i<=arb;i++)printf("%lld ",i);
return 0;
}

CF618F-Double Knapsack【结论】的更多相关文章

  1. CF618F Double Knapsack 构造、抽屉原理

    传送门 首先,选取子集的限制太宽了,子集似乎只能枚举,不是很好做.考虑加强限制条件:将"选取子集"的限制变为"选取子序列"的限制.在接下来的讨论中我们将会知道: ...

  2. CF618F Double Knapsack

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

  3. 【CF618F】Double Knapsack(构造)

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

  4. 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 ...

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

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

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

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

  7. 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_ ...

  8. 618F Double Knapsack

    传送门 题目大意 分析 代码 #include<iostream> #include<cstdio> #include<cstring> #include<s ...

  9. CodeForces - 618F Double Knapsack

    Discription You are given two multisets A and B. Each multiset has exactly n integers each between 1 ...

  10. vector族函数

     本文原创,转载请注明出处,本人Q1273314690 vector(mode = "logical", length = 0) as.vector(x, mode = " ...

随机推荐

  1. 查询liunx上磁盘占用情况

    查询挂载盘磁盘情况 df -h 查询指定目录下的文件夹内存占用情况 du -hs /*

  2. 什么是.NET CLI CLR IL JIT GC,它们是如何工作的

    参考网址: https://cloud.tencent.com/developer/article/1432891 1:什么是.NET? NET 是 Microsoft 的用以创建 XML Web 服 ...

  3. QT 编译的过程

  4. 04.SpringMVC之用

    分析 Spring MVC 是怎么处理请求的.首先分析 HttpServletBean.FrameworkServlet 和 DispatcherServlet 这三个 Servlet 的处理过程,最 ...

  5. linux 常用命令(五)——(centos7-centos6.8)JDK安装

    1.安装jdk前先检测系统是否带有OpenJDK:若存在则删除 查看: java -version 查询出OpenJDK相关的文件:rpm -qa | grep java 删除OpenJDK相关的文件 ...

  6. Vue.JS快速上手(Vue-router 实现SPA 开发)

    一.什么是路由 URL -> 映射 -> 组件 Hash+onhashchange History.pushstate+replaceState+onpopstate 二.准备工作 组件 ...

  7. redis百万级数据存取

    Jedis jedis0 = new Jedis("localhost", 6379); jedis0.auth("123456"); Pipeline pip ...

  8. 眼见为实,看看MySQL中的隐藏列!

    在介绍mysql的多版本并发控制mvcc的过程中,我们提到过mysql中存在一些隐藏列,例如行标识.事务ID.回滚指针等,不知道大家是否和我一样好奇过,要怎样才能实际地看到这些隐藏列的值呢? 本文我们 ...

  9. 用C++实现的增强Euler筛法程序

    运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...

  10. MySQL-基础-2

    MySQL数据库介绍 • MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理. • MySQL的历 ...