ABC388

好像已经很久没有写过题解了

C

link

对于每一个糕点,二分查找大于等于它大小的二倍的糕点的位置(可以用lowerbound函数),从这个位置到n就是可以和这个糕点配对的糕点。

猜猜我是啥
#include<bits/stdc++.h>

#define int long long

using namespace std;

int n;
int a[500005];
int ans;

signed main(){
	
	cin >> n;
	for(int i = 1;i <= n;++ i)
		cin >> a[i];
	
	for(int i = 1;i <= n;++ i){
		int w = a[i]*2;
		int wz = lower_bound(a+1,a+1+n,w)-a;
		ans += n-wz+1;
	}
	
	cout << ans;
	
	return 0;
	
}

D

link

dii成年时有的石头数。
首先我们可以得出,石头只会从前往后送;而且我们还可以得出,i成年后一共会送出min(ai,ni)个石头,也就是会让i+1i+min(ai,ni)这些人的石头数加一。
我们知道,区间加一可以用差分,可是差分要全做完之后做前缀和才能知道结果,怎么办呢?我们知道如果一个数成年了就不会再得到石头了,也就是说当我们需要知道di时,它就不会再改变了,那么我们就可以边差分边前缀和,做到哪一个需要它了就算到这个的前缀和,后面还是用差分去做区间加一。

猜猜我是啥
#include<bits/stdc++.h>

using namespace std;

int n;
int a[500005];
int cf[500005];

signed main(){
	
	cin >> n;
	for(int i = 1;i <= n;++ i)
		cin >> a[i],cf[i] = a[i]-a[i-1];
	
	for(int i = 1;i <= n;++ i){
		a[i] = cf[i-1]+cf[i];
		cf[i] += cf[i-1];
		int w = min(a[i],n-i);
		cf[i+1]++;
		cf[i+w+1]--;
		a[i] -= w;
	}
	
	for(int i = 1;i <= n;++ i)
		cout << a[i] << " ";
	
	return 0;
	
}

E

link

二分答案,对于一个答案x,我们考虑从前面选x个(最小的x个),从后面选x个(最大的x个),看看可不可以组起来(最小中最小的和最大中最小的组起来一直到最小中最大的和最大中最大的组起来),如果可以,就更大一些,如果不行就小一些。

猜猜我是啥
#include<bits/stdc++.h>

using namespace std;

int n;
int a[500005];

bool check(int x){
	for(int i = 1,j = n-x+1;i <= x;++ i,++ j){
		if(a[i]*2 > a[j]) return false;
	}
	return true;
}

signed main(){
	
	cin >> n;
	for(int i = 1;i <= n;++ i)
		cin >> a[i];
	
	int l = 0,r = n/2;
	while(l < r){
		int mid = (l+r+1)/2;
		if(check(mid)) l = mid;
		else r = mid-1;
	}
	cout << l;
	
	return 0;
	
}
posted @   不认命,就是哪吒的命!  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示