签到
作者:互联网
题目描述
背景:本来正在水群,计划12题,但是少了一题签到,群友给了建议(见样例下面的备注),就出了个签到题,在此感谢。
给定一个序列,你可以在序列中任取 44 个数 a,b,c,d (可以重复选取),问是否有一种选择满足:a+b+c=d。
输入描述:
第一行,一个正整数 n ( 1 <= n <= 1e3)
第二行 n 个整数 a1, a2, .... an (1 <= an <= 1e9)
输出描述:
如果存在一种情况满足,则输出"Yes"(不加引号),否则输出"No"(不加引号)。
样例
输入:
4
1 8 20 90
输出:
No
输入:
4
1 2 3 4
输出:
Yes
分析
暴力枚举三重 for 循环 + longn 的 二分查找, 必然会超时, 需要做的是, 将三重循环优化为两重
详情见代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010, M = 1e6 + 10;
int n, t, a[N], sum[M];
// 二分查找, 是否存在
bool find(int x)
{
int l = 1, r = t;
while(l < r)
{
int mid = l + r >> 1;
if(sum[mid] >= x) r = mid;
else l = mid + 1;
}
return sum[l] == x;
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
t = 1;
sort(a + 1, a + n + 1);
/*
要判断的等式为 a + b + c = d;
朴素写法的复杂度为 n^3*longn, 对于题目中的数据,必然超时
所以,先额外开一个数组 sum[],存放所有 a + b 的值 t
等式就变为 d - c = t 然后再用 二分寻找 t 是否 存在
*/
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
sum[t++] = a[i] + a[j];
sort(sum + 1, sum + t);
// 将三重 for 循环 优化为 两重
for(int i = n; i >= 1; i --)
{
for(int j = 1; j <= i; j ++)
{
int t = a[i] - a[j];
if(find(t))
{
cout << "Yes" << endl;
return 0;
}
}
}
cout << "No" << endl;
return 0;
}
标签:二分,输出,签到,sum,mid,int,include 来源: https://www.cnblogs.com/ding-yu/p/16488291.html