二分答案二分搜索專題

在這裏插入圖片描述
在這裏插入圖片描述

題目大意:
給你一個長度爲nn的字符串,只包含aba 或者 b,現在你可以將aa換成bkb,k次,或bb換成aa,問你換完後最長的只有包含一個字符的子串長度是多少。
思路:
先求一下,字符aa和字符bb的前綴和,然後枚舉起點,二分終點位置。
代碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
char s[maxn];
int a[maxn],b[maxn];
void solved(){
	int n,k;cin>>n>>k;
	scanf("%s",s + 1);
	for(int i = 1; i <= n; i++){
		if(s[i] == 'a'){
			a[i] = a[i - 1] + 1;b[i] = b[i - 1];
		}else{
			b[i] = b[i - 1] + 1;a[i] = a[i - 1];
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; i++){
		int l = i,r = n;
		while(l <= r){
			int mid = l + r >> 1;
			if(a[mid] - a[i - 1] <= k || b[mid] - b[i - 1] <= k){
				ans = max(ans,mid - i + 1);l = mid + 1; 
			}else{
				r = mid - 1;
			}
		}
	}
	cout<<ans<<endl;
}
int main(){
	solved();
	return 0;
} 

在這裏插入圖片描述
在這裏插入圖片描述
題目大意:
給你nn個數,要你找到最多有多少對滿足aiaj<=k|ai-aj|<=k的二元組。
思路:
先排序,然後暴力枚舉前面n/2n/2個點,然後二分出第一個大於等於ai+zai+z的數,並且這個數字沒有與其他數配對,所以就是一個lower_bound加一個條件!vis[mid]!vis[mid]即可。
代碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 10;
typedef long long int ll;
ll a[maxn],n,z;
bool vis[maxn];
void solved(){
	cin>>n>>z;
	for(int i = 1; i <= n; i++)cin>>a[i];
	sort(a + 1, a + 1 + n);
	a[n + 1] = 1e18;
	ll ans = 0;
	for(int i = 1; i <= n/2; i++){
		ll v = a[i] + z;
		int l = 1,r = n + 1;
		int pos = 0;
		while(l <= r){
			int mid = l + r >> 1;
			if(a[mid] >= v && !vis[mid])pos = mid,r = mid - 1;
			else l = mid + 1;
		} 
		if(pos == n + 1)continue;
		ans ++;
		vis[i] = true;
		vis[pos] = true;
	}
	cout<<ans<<endl;
}
int main(){
	solved();
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章