[codeforces 618 F] Double Knapsack (抽屉原理)
题目链接:http://codeforces.com/contest/618/problem/F
题目:

题目大意:
有两个大小为 N 的可重集 A, B, 每个元素都在 1 到 N 之间. 分别找出 A 和 B 的一个子集, 使得这两个子集元素之和相等.
分别输出集合A和集合B的子集的个数以及子集中元素在原集合中的位置
N ≤ $10^6$
题解:
首先我们证明一个结论,存在一组方案,满足两个子集在A中和在B中都是连续的一段
把两个集合看成两个数组,分别计算出前缀和sa,sb
对于每个i(0<=i<=n),我们j为满足0<=sa[i]-sb[j]<=n-1的最大的j,设d[i]=sa[i]-sb[j],可以发现j的单调递增的
我们发现d数组一共有n+1个元素(包括i=0,sa[i]=0的情况),并且我们又发现d[i]的取值只有n个。那么根据抽屉原理,至少有两个d数组中的元素是相等的
于是我们有sa[i']-sb[j']=sa[i]-sb[j](i'>i)
移项之后得到sa[i']-sa[i]=sb[j']-sb[j]
这个时候我们就知道在A数组中i+1~i'这一段元素之和与B数组中j+1~j'这一段元素之和相等
证毕
其实上面的证明过程就是我们本题的做法,我们用two pointers处理出d数组,然后判断当前的d值在之前是否出现过,这个时候我们就得到了答案
值得注意的是,我们需要sa[n]<=sb[n],因为若是sa[n]>sb[n]可能出现对于i=n找不到一个j满足上述条件
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std; const int N=1e6+;
int n,cnt1,cnt2,st1,st2,ed1,ed2;
int sa[N],sb[N],vis[N],p[N];
inline int read()
{
char ch=getchar();
int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void solve(int a[],int b[])
{
memset(vis,-,sizeof(vis));
int j=;
for (int i=;i<=n;i++)
{
while (a[i]-b[j]>=n) j++;
int d=a[i]-b[j];
if (vis[d]!=-)
{
cnt1=i-vis[d];
st1=vis[d]+;ed1=i;
cnt2=j-p[vis[d]];
st2=p[vis[d]]+;ed2=j;
break;
}
vis[d]=i;p[i]=j;
}
}
int main()
{
n=read();
for (int i=;i<=n;i++) sa[i]=sa[i-]+read();
for (int i=;i<=n;i++) sb[i]=sb[i-]+read();
if (sa[n]<=sb[n])
{
solve(sa,sb);
}
else
{
solve(sb,sa);swap(cnt1,cnt2);swap(st1,st2);swap(ed1,ed2);
}
printf("%d\n",cnt1);
for (int i=st1;i<=ed1;i++) printf("%d ",i);
printf("\n");
printf("%d\n",cnt2);
for (int i=st2;i<=ed2;i++) printf("%d ",i);
printf("\n");
return ;
}
[codeforces 618 F] Double Knapsack (抽屉原理)的更多相关文章
- 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 ...
- CF618F Double Knapsack 构造、抽屉原理
传送门 首先,选取子集的限制太宽了,子集似乎只能枚举,不是很好做.考虑加强限制条件:将"选取子集"的限制变为"选取子序列"的限制.在接下来的讨论中我们将会知道: ...
- 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_ ...
- CodeForces 485A Factory (抽屉原理)
A. Factory time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- Codeforces Round #319 (Div. 2) B. Modulo Sum 抽屉原理+01背包
B. Modulo Sum time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- Codeforces 958C3 - Encryption (hard) 区间dp+抽屉原理
转自:http://www.cnblogs.com/widsom/p/8863005.html 题目大意: 比起Encryption 中级版,把n的范围扩大到 500000,k,p范围都在100以内, ...
- 51nod 1103 N的倍数(抽屉原理)
1103 N的倍数 题目来源: Ural 1302 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍 ...
- 【CF618F】Double Knapsack(构造)
[CF618F]Double Knapsack(构造) 题面 洛谷 Codeforces 题解 很妙的一道题. 发现找两个数集很不爽,我们强制加强限制,我们来找两个区间,使得他们的区间和相等. 把区间 ...
- bzoj#4722-由乃【倍增,抽屉原理,bitset】
正题 题目链接:https://darkbzoj.tk/problem/4722 题目大意 给出一个长度为\(n\)的序列值域为\([0,v)\),要求支持操作 询问一个区间能否找到两个没有交的非空下 ...
随机推荐
- webstorm卡顿问题处理
webstorm卡顿问题处理 学习了:http://blog.csdn.net/qq673318522/article/details/50583831 找到WebStorm.exe.vmoption ...
- 上机题目(0基础)-计算两个正整数的最大公约数和最小公倍数(Java)
题目例如以下:
- Swift基础--定位
// // ViewController.swift // JieCoreLocation // // Created by jiezhang on 14-10-4. // Copyright (c) ...
- oracle刚開始学习的人经常使用操作100问
oracle刚開始学习的人经常使用操作100问 1. Oracle安装完毕后的初始口令? internal/oracle sys/change_on_install system/manager ...
- iOS 自己主动登录,登录过程中一直显示载入页
iOS开发中 假设client做的人性化一点肯定会考虑自己主动登录 事实上原理非常easy,就是再首次登录成功之后将username和password存入userdefault 下次登录的时候推断us ...
- 创建表空间及plsql查看远程表空间路径
-新建表空间,登录名和密码 --请尽量把表空间和别的系统分离,这里以Search为例子,登录名和密码以test为例子 create tablespace Search logging datafile ...
- 移动端video播放时不弹出页面层
移动端视频在播放时会主动弹出页面,有的浏览器不会.对那些会的浏览器进行处理: 直接加上下面三个属性即可,兼容方面就不说了,微信上是很ok的. <video x5-playsinline=&quo ...
- STL数组和com数组相互转换的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 STL的泛型数组是vetor,com的泛型数组类型是VARIANT.二者怎样能相互转化呢?就是说怎么把一个vector ...
- 机器学习(十一) 支持向量机 SVM(上)
一.什么是支撑向量机SVM (Support Vector Machine) SVM(Support Vector Machine)指的是支持向量机,是常见的一种判别方法.在机器学习领域,是一个有监督 ...
- Caffe Loss分析
Caffe_Loss 损失函数为深度学习中重要的一个组成部分,各种优化算法均是基于Loss来的,损失函数的设计好坏很大程度下能够影响最终网络学习的好坏.派生于 \(LossLayer\),根据不同的L ...