A:最大回撤
知识点:枚举
思路:枚举每个数值x,求出前i个数最大值与x的差值,n个差值中最大的那个就是答案(也就是,输入一个数,求出最大值,这个最大值就是前i个数的最大值,再减去每次输入的x就是商品最大可能的亏损价格)。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,x,maxn=INT_MIN,ans=INT_MIN;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
maxn=max(maxn,x);
ans=max(ans,maxn-x);
}
if(ans==INT_MIN) cout<<0;
else cout<<ans;
return 0;
}
B:连续的零
知识点:字符串、滑动窗口法
思路:首先统计出前k个字符中出现1的个数,作为答案的初始值,其次指针从k+1开始走到n,每次都统计区间i-k+1到i区间的1的个数(也就是每次指针向后遍历一次,累加第i个位置的字符1,减去i-k个位置的字符1),随时取其最小值即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,k,cnt,ans;
string s;
int main(){
cin>>n>>k>>s;
for(int i=0;i<k;i++){
if(s[i]=='1'){
cnt++;
}
}
ans=cnt;
for(int i=k;i<n;i++){
cnt+=s[i]-s[i-k];
ans=min(ans,cnt);
}
cout<<ans;
return 0;
}
C:B进制星球
知识点:高精度、进制转换
思路:将输入的字符串倒序存储在数组中(注意大于等于16进制的情况),再利用高精度加法原理来进行相加两个数组,其和的长度为两个加数中最大的加1,再考虑进位处理,遇到了n就向高位进位,最后再去除前导零,逆序输出即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,x[2112],y[2112],z[2112];
string a,b;
int main() {
cin>>n>>a>>b;
x[0]=a.size(),y[0]=b.size();
z[0]=max(x[0],y[0])+1;
for(int i=0,j=x[0]; i<x[0]; i++,j--)
if(a[i]>='A') x[j]=a[i]-'A'+10;
else x[j]=a[i]-'0';
for(int i=0,j=y[0]; i<y[0]; i++,j--)
if(b[i]>='A') y[j]=b[i]-'A'+10;
else y[j]=b[i]-'0';
for(int i=1; i<=z[0]; i++) {
z[i]+=x[i]+y[i];
if(z[i]>=n) {
z[i+1]+=z[i]/n;
z[i]%=n;
}
}
while(z[0]&&z[z[0]]==0)z[0]--;
for(int i=z[0]; i>=1; i--) {
if(z[i]>=10)cout<<char('A'+z[i]-10);
else cout<<z[i];
}
return 0;
}
D:物品分组
知识点:二分
思路:在最小值(物品价值最小值)和最大值(所有物品价值之和)之间进行二分搜索,检查是否存在一种分组方式(检查在不超过中间值m的数量是否能够分组数),使得所有子数组的和不超过当前中间值,若可以分出k组,那么统计答案,再将最大值放小,否则将最小值放大。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[1001],k,l=INT_MAX,m,r,ans;
bool check(int m) {
int s=0,g=1;
for(int i=1; i<=n; i++) {
if(m<a[i]) return 0;
if(s+a[i]<=m) {
s+=a[i];
} else {
g++;
s=a[i];
}
}
return g<=k;//g<=k说明组数可能不够,也就意味着m可以再调大
}
int main() {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
l=min(l,a[i]);
r+=a[i];
}
cin>>k;
while(l<=r) {
m=l+(r-l)/2;
if(check(m)) { //m可以分出k组
ans=m;
r=m-1;
} else {
l=m+1;
}
}
cout<<ans;
return 0;
}