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;
}

浙公网安备 33010602011771号