Skibidus and Fanum Tax (hard version)

题目链接:https://codeforces.com/problemset/problem/2065/C2

题意:

给定两个序列a,b,长度分别为n和m,对于所有的a序列元素允许操作一次:选择1<=j<=m,使得a[i]=b[j]-a[i],试问能否通过操作将a序列变为单调不递减的?

思路:

从左往右看,发现我可以令每个元素尽量小,同时要大于等于前面一个元素,这样能为后面的元素提供更多机会
如果要换,那么有 b[j]-a[i]>=a[i-1] = > b[j] >= a[i]+a[i-1]

因此可以通过排序+二分的形式求出最满意的b[j],(注意如果lower_bound二分没找到大于等于这个元素,说明整个序列的元素都小于这个元素,返回尾迭代器,此时b.end()-b.begin()=len,即返回数组总长度)
(如果没找到,直接continue,因为换了之后就不满足非递减)

此时决定换不换,如果原先元素不满足非递减那肯定要换。
如果原先元素和前一个元素差值比较大也考虑换
反之就不换,会更优

闲聊:

最近开始刷cf了,感觉之前练习的方式不对,还是刷题比较能提示实力呀

void solve(){
	int n,m;cin>>n>>m;
	vector<int>a(n+1);
	vector<int>b(m+1);
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=m;i++)cin>>b[i];
	sort(b.begin()+1,b.end());
	for(int i=1;i<=n;i++){
		if(i==1){
			if(a[i]>b[1]-a[i])a[i]=b[1]-a[i];
		}else{
			int dif=a[i]-a[i-1];
			int sum=a[i]+a[i-1];
			int pos=lower_bound(b.begin()+1,b.end(),sum)-b.begin();
			if(pos==m+1)continue;
			
			int dif2=b[pos]-a[i]-a[i-1];
			if(dif<0){
				a[i]=b[pos]-a[i];
				continue;
			}
			if(dif2<dif)a[i]=b[pos]-a[i];
		}
	}
	int ok=1;
	for(int i=1;i<=n-1;i++){
		if(a[i]>a[i+1])ok=0;
	}
	if(ok)cout<<"yes"<<endl;else cout<<"no"<<endl;
}
posted @ 2025-03-20 20:36  Marinaco  阅读(63)  评论(0)    收藏  举报
//雪花飘落效果