第三周第一场比赛题解(二分)
1、计蒜客 T1560 二分查找(一)
题意:
给你一个长度为n的数组,然后询问m次,问给你的数字在数组里面没有,如果在输出YES 不在输出NO.
思路:
二分或者直接下标记录或者可以采用set集合查找
代码:
(1)因为这道题他说了询问的数字x不会超过1e6,那么我们就可以将输入的数字作为数组的下标,然后直接查询。复杂度O(1)
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N];
int main()
{
ios_base::sync_with_stdio(NULL);
cin.tie(NULL),cout.tie(NULL);
int n,m,x;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>x;
if(x < N - 1) ///预防输入的数字有超过1e6的
a[x] = 1;
}
int q;
while(m--){
cin>>q;
if(a[q])
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
(2)直接将数字存入,然后二分查找
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N];
int main()
{
ios_base::sync_with_stdio(NULL);
cin.tie(NULL),cout.tie(NULL);
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);///二分前提需要数组有序
int q;
while(m--){
cin>>q;
int flag = 0;
int l = 0,r = n - 1;
while(l <= r){
int mid = (l+r) / 2;
if(a[mid] < q)
l = mid + 1;
else if(a[mid] > q)
r = mid - 1;
else if(a[mid] == q){
flag = 1;
break;
}
}
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
2、计蒜客 T1413 找球号
题意:
和第一题一样的,给你一个长度为 n n n的数组,然后询问 m m m次,问给你的数字在数组里面没有,如果在输出 Y E S YES YES 不在输出 N O NO NO.
思路:
和第一题一样。可以采用二分,map记录,set查找,map查找
这道题有点坑哈,需要用scanf 不然会超时。
代码:
基本二分
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
int q;
while(m--){
scanf("%d",&q);
int flag = 0;
int l = 0,r = n - 1;
while(l <= r){
int mid = (l + r) >> 1;
if(a[mid] < q)
l = mid + 1;
else if(a[mid] > q)
r = mid - 1;
else{
flag = 1;
break;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
3、计蒜客 T1966 假币问题
题意:
如题,签到题
思路:
(1 2 3都只需要一次)直接模拟天平称重。
和第一题一样。可以采用二分,map记录,set查找,map查找
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int cnt = 0;
while(n > 3){
n /= 2;
cnt ++;
}
cout<<cnt + 1<<endl;
return 0;
}
4、计蒜客 T3062 蜗牛旅游
题意:
就是给你一个序列,让你求出最长的一个连续子序列(即这个子序列里面没有重复的数字)
思路:
1.队列,遍历数组依次入队,如果当前这个数字出现了,就将这个数字前面出现的那次 前面的所有数字全部出队。这样就可以保证队列里面都是没有重复数字的,然后维护队列最大值即可。
2.二分答案。只需要二分长度,然后写一个check函数就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
queue<int> qe;
int vis[N],a[N];
int main()
{
int n;
cin>>n;
int ans = -1;
for(int i = 0;i< n ;i++){
cin>>a[i];
}
for(int i = 0;i < n;i++){
if(vis[a[i]] == 0){
qe.push(a[i]);
vis[a[i]] = 1;
}else{
while(vis[a[i]] != 0){
vis[qe.front()] = 0;
qe.pop();
}
qe.push(a[i]);
vis[a[i]] = 1;
}
int len = qe.size();
ans = max(ans,len);
}
cout<<ans<<endl;
return 0;
}
4、CF 195A Let’s Watch Football
题意:
就是a、b、c三个数字,a表示每一秒多少数据,b表示每一秒下载多少,c表示视频有多长。问你再开始缓冲多少秒可以使得到观看结束不在缓冲。
思路:
也就是边观看边下载,然后观看的时间可以把没有缓冲的下完。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,c;
cin>>a>>b>>c;
int ans = (a - b) * c / b;
if(((a - b) * c )% b)
ans ++;
cout<<ans<<endl;
return 0;
}