题意:给定一个操作使1到i的数字加1,而后面的数字减1,问最少多少次操作使得这个数组是无序的
思路:我们枚举后者减前者的最小的那个位置,每次我们可以让他减少2,直接求解次数即可,减为负数即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t ;
void solve(){
int n;
cin>>n;
int ma,ls,x;
ma=1e9;
for (int i = 0; i <n ; ++i) {
ls=x;
cin>>x;
if(i>0){
ma=min(ma,x-ls);
ls=x;
}
}
cout<<max((ma+2)/2,(int)0)<<'\n';
}
signed main(){
t=1;
cin>>t;
while (t--){
solve();
}
}
题意:给定一个n和k,问我可以形成多少个结尾位n的,个数为k的类斐波那契数列
思路:直接暴力枚举倒数第二个位置的数字为多少即可,我们枚举到如果形成了>k的个数,且第一个位置是非负数,那么以这个数位倒二结尾的这个数列就是合法的,我们枚举到负数时直接break,复杂度很低
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t ;
void solve(){
int n,k;
cin>>n>>k;
int l=0,r=0;
int ans=0;
for (int i = 0; i <=n ; ++i) {
int ls=n;
int dq=i;
int cnt=2;
while (1){
int g=dq;
dq=ls-dq;
ls=g;
if(dq>=0){
cnt++;
if(cnt>k){
// cout<<i<<endl;
ans++;
break;
}
}
else break;
}
// if(cnt==k){
// cout<<i<<endl;
// ans++;
// }
}
cout<<ans<<endl;
}
signed main(){
t=1;
cin>>t;
while (t--){
solve();
}
}
题意:给一个无限长的序列,我们每次可以删除第a1,a2,a3,a4……的位置的数字,问我们删除k次之后,最小的那个,也就是第一个数字是多少
思路:我们可以二分答案,二分枚举这个数字,假设我们删除的是 1 3 5 6 7,我们枚举到9时,我们发现当前9的位置是9,那我们可以从这个数组中找到他之前被删除了多少个数字,我们直接upper(当前位置)得到的是最后一个位置+1然后减去首地址,得到前面删除了5个数字,那么当前的9的位置就从9变成了9-5=4,然后我们第二次upper(当前位置4),我们得到前面删除了2个数字,那么9当前位置是4-2为2,第三次删除,upper(2),得到前面删除了1个数字,当前9位置就变成了1,如果我们把9已经删除了,我们会得到9的位置<=0,那么我们就更新左区间l,使mid更大,否则我们取答案,更新r
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n,k;
cin>>n>>k;
vector<int >a(n);
for (int i = 0; i <n ; ++i) {
cin>>a[i];
}
auto check=[&](int mid){
for (int i = 1; i <=k ; ++i) {
int cnt= upper_bound(a.begin(),a.end(),mid)-a.begin();
mid-=cnt;
if(mid<=0)return false;
}
return true;
};
int l=1,r=2e14;
int ans=-1;
while(l<=r){
int mid=l+r>>1;
if(check(mid)){
r=mid-1;
ans=mid;
}
else l=mid+1;
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while (t--){
solve();
}
}