2020.4.12 字节笔试题 B dp D 单调栈

A 简单交换

水题。。

B--折木棍

解法来自群友

f[i][j]:第i个木棍拆成最大值为j使前面满足条件的最小拆法次数
贪心得到一个这种拆法的木棍最小值X和次数S
f[i][j]=max(f[i-1][k]+s)  k<=x

其实就是 每个木棍a[i]  枚举最大值是len  (最右边是len) 以及最左边: a[i]%len  计算最小拆法:s=a[i]/len+((a[i]%len==0)?0:1)-1 

按照每个位置都是len   最左边的数要么是a[i]%len  要么是len  那如何计算 最左边的合法的最大值呢?pos+1个数 平均a[i]就好了 k=a[i]/(pos+1)

#include<bits/stdc++.h>
#define LL long long
using namespace std;

LL a[3005], f[3005][3005];

int main() {

    int n; scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%lld", &a[i]);
    }
    memset(f, 7, sizeof(f));
    for(int i=0; i<3005; i++) f[0][i]=0;

    for(int i=1; i<=n; i++){
        for(int len=1; len<3005; len++){
            if(len>a[i]){
                f[i][len]=f[i][len-1];
                continue;
            }
            LL pos=a[i]/len+((a[i]%len==0)?0:1)-1;//按照mi len len len 切的次数pos
            LL mi=((a[i]%len==0)?len:(a[i]%len));
            //pos*len+mi==a[i]
            LL x=(pos*len+mi)/(pos+1);//切pos刀有pos+1个位置,a[i]平均分给pos+1个位置就是最大合法的值x

            //printf("mi:%lld x:%lld\n",mi,x);
            f[i][len]=f[i-1][x]+pos;
            f[i][len]=min(f[i][len], f[i][len-1]);
            //cout<<i<<" "<<len<<" "<<f[i][len]<<endl;
        }
    }
    LL ans=1<<30;
    for(int i=1; i<=a[n]; i++){
        ans=min(ans, f[n][i]);
    }
    printf("%lld\n", ans);

    return 0;
}
/*
5
3 5 13 9 12
ans:1

5
5 4 3 2 1
ans:
*/

C--优惠券

对a排序,b[i]在a中二分即可。

D--站得高 看得远

经典单调栈题

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e6+10;
int a[N],ans[N],n,m,l[N],r[N];
int main()
{
   int _;cin>>_;while(_--)
   {
       scanf("%d",&n);
       rep(i,1,n) scanf("%d",&a[i]);
       stack<int>sta;
       rep(i,1,n) l[i]=r[i]=i;
       for(int i=1;i<=n;++i){
            if(sta.size()==0) sta.push(i);
            else{
                while(sta.size()&&a[i]>=a[sta.top()]) {
                    sta.pop();
                }
                if(sta.size()) l[i]=sta.top()+1;
                else l[i]=1;
                sta.push(i);
            }
       }
       while(sta.size()) sta.pop();

       for(int i=n;i;--i){
            if(sta.size()==0) sta.push(i);
            else{
                while(sta.size()&&a[i]>=a[sta.top()]) {
                    sta.pop();
                }
                if(sta.size()) {
                    r[i]=sta.top()-1;

                }
                else r[i]=n;

                sta.push(i);
            }
       }
       rep(i,1,n)
       {
           printf("%d ",r[i]-l[i]);
       }
       puts("");


   }
}
发布了519 篇原创文章 · 获赞 69 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/105486761