C. Really Big Numbers
题意:问有多少个<=n的数x,x减去x的各位数字之和>=s
思路:对于千位数我们把他看成1000x+100y+10z+g-x-y-z-g>=s,得到111x+11y+z>=s/9;
则由此得知,当xyz越大时,左边越大,单增的,标准做法是二分找到>=s的边界数,我的做法是求出xyz的临界值,但WA19
代码:
正确:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int mid;
int n,s;
bool check(int x){
int sum=0;
int y=x;
while (y){
sum+=y%10;
y/=10;
}
return x-sum>=s;
}
signed main(){
cin>>n>>s;
int l=1,r=n;
int ans=-1;
while(l<=r){
mid=l+r>>1;
if(check(mid)){
r=mid-1;
ans=mid;
}
else{
l=mid+1;
}
}
if(ans==-1){
cout<<"0\n";
}
else{
cout<<n-ans+1;
}
}
WA18:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
signed main(){
int n,s;
cin>>n>>s;
s=(s+8)/9;
int cnt=0;
vector<int >q;
int p=n;
if(s==0){
cout<<n;
return 0;
}
while(p){
cnt++;
p=p/10;
}
cnt--;
cnt--;
int s1=1;
for (int i = 0; i <cnt ; ++i) {
s1=10*s1+1;
}
vector<int>ws;
if(s/s1>9){
cout<<'0';
return 0;
}
while (1){
int g=s/s1;
s=s%s1;
if(s==0) {
g--;
ws.push_back(g);
break;
}
ws.push_back(g);
s1/=10;
if(s1==0)break;
}
int ans=0;
int ct=0;
for (int i =0 ; i <ws.size() ; ++i) {
ans=ans*10+ws[i];
ct++;
}
// cout<<ans<<endl;
while (ct<=cnt+1) {
ans = ans * 10 + 9;
ct++;
}
if(n-ans<0){
cout<<"0";
}
else{
cout<<n-ans;
}
}
D. Imbalanced Array
题意:给一个数组,l,r任取,l到r之中,问最大值和最小值的差的和是多少
思路:我们可以发现一个数的贡献是他作为最大的值的贡献和作为最小值的贡献,就是找到它左边比他大的值的位置,找到它右边比它大的值的位置,因为可能有等于,我们端点取一方,中间的都是他能够影响到的区间,则他的贡献就是(i-ma左)(ma右-i)a[i],然后再算最小值,计算这个我们用到单调栈,一边取等号,另一边不取等号
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int a[1000005],mil[1000005],mir[1000005],mal[1000005],mar[1000005];
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(nullptr);
int n;
cin>>n;
for (int i = 1; i <=n ; ++i) {
cin>>a[i];
}
stack<int>st;
//左边最大的
st.push(0);
a[0]=1e7;
a[n+1]=1e7;
for (int i = 1; i <=n ; ++i) {
while(a[i]>=a[st.top()])st.pop();
mal[i]=i-st.top();
st.push(i);
}
st.push(n+1);
//右边比他大的
for (int i = n; i >=1 ; --i) {
while(a[i]>a[st.top()])st.pop();
mar[i]=st.top()-i;
st.push(i);
}
//左边小
a[0]=a[n+1]=0;
st.push(0);
for (int i = 1; i <=n ; ++i) {
while(a[i]<=a[st.top()])st.pop();
mil[i]=i-st.top();
st.push(i);
}
st.push(n+1);
//右边比他小的
for (int i = n; i >=1 ; --i) {
while(a[i]<a[st.top()])st.pop();
mir[i]=st.top()-i;
st.push(i);
}
int ans=0;
for (int i = 1; i <=n ; ++i) {
ans+=a[i]*(mar[i]*mal[i]-mir[i]*mil[i]);
}
cout<<ans<<endl;
}