【CodeForces 620D】Professor GukiZ and Two Arrays
题意
两个数列,一个有n个数,另一个有m个数,让你最多交换两次两个数列的数,使得两个数列和的差的绝对值最小,求这个差的绝对值、最少交换次数、交换数对
分析
交换0次、1次可得到的最小的差可以枚举出来。
交换两次,如果枚举就超时了。
我们预处理把第一个数列两两组合的所有情况存储起来为u数组,并且按照大小排序,接着在另一个数列里枚举两个数后,用二分的方法,求交换后使得 差的绝对值最小 的u。
二分查找最接近的值可以用lower_bound函数。
代码
#include<stdio.h>
#include<cmath>
#include<map>
#include<utility>
#define N 2005
#define ll long long using namespace std;
ll a[N],b[N],n,m,suma,sumb,v,ans,c; map<ll,pair<int,int> >u;
map<ll,pair<int,int> >::iterator it;
pair<int,int>swap1,swap2; void update(int i,int j)
{
if(abs(c-it->first) < v)
{
ans=;
v = abs(c - it->first);
swap1 = it->second;
swap2 = {i,j};
}
} int main()
{
scanf("%lld",&n);
for(int i=; i<=n; i++)
{
scanf("%lld",&a[i]);
suma+=a[i];
} scanf("%lld",&m);
for(int i=; i<=m; i++)
{
scanf("%lld",&b[i]);
sumb+=b[i];
} v=abs(suma-sumb);
if(!v)
{
printf("0\n0\n");
return ;
} for(int i=; i<n; i++)
for(int j=i+; j<=n; j++)
u[(a[i]+a[j])*2LL] = {i,j}; for(int i=; i<=n; i++)
for(int j=; j<=m; j++)
if(abs(suma-sumb-2LL*(a[i]-b[j]))<v)
{
ans=;
v=abs(suma-sumb-2LL*(a[i]-b[j]));
swap1= {i,j};
}
for(int i=; i<m; i++)
for(int j=i+; j<=m; j++)
{
c=suma-sumb+2LL*(b[i]+b[j]);
it=u.lower_bound(c);
if( it != u.end() )
update(i,j);
if( it != u.begin() )
{
it--;
update(i,j);
}
} printf("%lld\n%lld\n",v,ans); if(ans==)printf("%d %d\n",swap1.first,swap1.second);
if(ans==)printf("%d %d\n%d %d\n",swap1.first,swap2.first,swap1.second,swap2.second); return ;
}
2017.7.21 ps. 今天再做这题,wa了八下。因为自己写的二分,一开始忘记考虑n==1的情况(这样就不存在a数组里选两个加起来了,二分的结果没有意义)。之后发现我二分查找的是加了绝对值的,显然不需要加绝对值。以及如果二分查找的值不存在,那么得到的就是大于它的第一个值,所以还要考虑小于它的第一个值。最终AC的代码如下:
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
#define N 2001
int n,m,a[N],b[N];
struct Node{
ll a,b,v;
}sum[N*N];
ll sa,sb;
int x[],y[];
int cnt;
ll ans;
bool cmp(const Node& a,const Node& b){
return a.v<b.v;
}
int bs(ll s){
int l=,r=cnt;
while(l<r){
int mid=l+r>>;
if(sum[mid].v<s)
l=mid+;
else
r=mid;
}
return l;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;++i)
scanf("%d",a+i),sa+=a[i];
scanf("%d",&m);
for(int i=;i<=m;++i)
scanf("%d",b+i),sb+=b[i]; for(int i=;i<n;++i)
for(int j=i+;j<=n;++j)
sum[++cnt]=(Node){i,j,2LL*(a[i]+a[j])}; ans=abs(sb-sa); sort(sum+,sum++cnt,cmp);
int k=; for(int i=;i<=n;++i)
for(int j=;j<=m;++j){
ll t=abs(sa-a[i]*-sb+b[j]*);
if(t<ans){
ans=t;
k=;
x[]=i;y[]=j;
}
}
if(cnt){
for(int i=;i<m;++i)
for(int j=i+;j<=m;++j){
ll t=sa-sb+2LL*(b[i]+b[j]);
int d=bs(t);
for(int g=-;g<;++g)if(d+g>&&d+g<=cnt){
ll tans=abs(t-sum[d+g].v);
if(tans<ans){
ans=tans;
k=;
x[]=sum[d+g].a;y[]=i;
x[]=sum[d+g].b;y[]=j;
}
}
}
}
printf("%lld\n%d\n", ans,k);
for(int i=;i<k;++i)
printf("%d %d\n",x[i],y[i]);
return ;
}
【CodeForces 620D】Professor GukiZ and Two Arrays的更多相关文章
- CodeForces 620D Professor GukiZ and Two Arrays 双指针
Professor GukiZ and Two Arrays 题解: 将a数组都sort一遍之后, b数组也sort一遍之后. 可以观察得到 对于每一个ai来说, 整个数组bi是一个V型的. 并且对于 ...
- 【codeforces 415D】Mashmokh and ACM(普通dp)
[codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...
- Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays 二分
D. Professor GukiZ and Two Arrays 题目连接: http://www.codeforces.com/contest/620/problem/D Description ...
- Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays
Professor GukiZ and Two Arrays 题意:两个长度在2000的-1e9~1e9的两个序列a,b(无序);要你最多两次交换元素,使得交换元素后两序列和的差值的绝对值最小:输出这 ...
- 【24.67%】【codeforces 551C】 GukiZ hates Boxes
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【74.89%】【codeforces 551A】GukiZ and Contest
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【19.46%】【codeforces 551B】ZgukistringZ
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【codeforces 757B】 Bash's Big Day
time limit per test2 seconds memory limit per test512 megabytes inputstandard input outputstandard o ...
- 【codeforces 707E】Garlands
[题目链接]:http://codeforces.com/contest/707/problem/E [题意] 给你一个n*m的方阵; 里面有k个联通块; 这k个联通块,每个连通块里面都是灯; 给你q ...
随机推荐
- ZOJ 1109 Language of FatMouse
较简单字典树,每输入一对字符串,前一个放在字典(数组)中,后一个插入字典树中,并将其最终的flag赋为前一个在数组中的下标,再就好找了.输入的处理方法要注意一下. 代码: #include <i ...
- JS中的基本运动逻辑思想总结
总结一下自己今天学习运动的基本思想:‘ [1]对于移动的div,使其在某一个位置停止将其封装成一个函数,仅仅改变speed的正负即可 涉及到问题包括: var time=null; function ...
- 第一次使用Android Studio时你应该知道的一切配置(三):gradle项目构建
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- Android SQLite (三 ) 全面详解(一)
官网 SQLite是一款轻型的数据库,是关系型数据库(RDBMS)管理系统,它包含在一个相对小的C库中.目前在很多嵌入式产品中使用了它,它占用资源非常 的低,在嵌入式设备中,可能只需要几百K的内存就够 ...
- c# 二进制或算法实现枚举的HasFlag函数
from:http://www.cnblogs.com/icyJ/archive/2013/02/20/HasFlag.html 在权限的管理中,常常会出现一个权限包含的现象.例如,有三种基本权限:职 ...
- 作业调度Quartz.NET
Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不牺牲 ...
- 装了个干净的win7
lanny的电脑基本信息 我的电脑 联想 ThinkPad T450s 笔记本电脑 操作系统 Windows 旗舰版 64位 主显卡 集成显卡 IE浏览器 版本号 8.0 基本硬件展示 处理器 英特尔 ...
- 矩形覆盖-我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
class Solution { public: int rectCover(int number) { ; ; ; ||number==) ; ) ; ;i<number+;i++){ res ...
- log4j发送邮件乱码
Log4J发日志邮件给多个接收者及标题.正文乱码问题 以前开发的系统没有单独的日志管理,所有的日志统一输出到tomcat后台一个文件里,不几天就是好几G,现在要整体增加一个Log4J管理日志的功能,其 ...
- 《WCF服务编程第三版》知识点摘录