[Offer收割]编程练习赛95

6 篇文章 0 订阅
5 篇文章 0 订阅

题目1 : 浇花问题

描述

小Hi在一条小路上种植了一排月季,总共有N株。这条小路的一端是一个水龙头。N株月季距离水龙头由近到远的距离依次是A1, A2, ... AN,每天需要浇水的量依次是B1, B2, ... BN。  

现在小Hi有一个容量是C的水壶。他从水龙头出发,拎着灌满的水壶,依次去浇灌第1株、第2株、第3株…… 如果浇完第K株时,小Hi发现水壶中剩余的水量不足以浇灌第K+1株,他会回到水龙头处,将水壶灌满水,再依次去浇灌第K+1株、第K+2株……

最终小Hi浇完第N株之后,回到水龙头处。你能计算小Hi一共行走的距离是多少吗?

输入

第一行包含两个整数N和C。  

第二行包含N个整数A1, A2, ... AN。  

第三行包含N个整数B1, B2, ... BN。  

1 <= N <= 100000  

1 <= Ai <= 1000000  

1 <= Bi <= 10000  

max(Bi) <= C <= 100000000  

输出

一个整数代表答案

样例输入

3 10  
1 3 5  
5 4 5

样例输出

16

题意:很清楚模拟即可

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long

using namespace std;
const int maxn=1e5+100;
LL a[maxn],b[maxn];
LL d[maxn];
int main()
{
    int n;
    LL c;
    scanf("%d%lld",&n,&c);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;i++)
    {
        d[i]=a[i]-a[i-1];
    }
    LL ans=0,cnt=0,v=c;
    for(int i=1;i<=n;i++)
    {
        if(v>=b[i])
        {
            v-=b[i];
            ans+=d[i];
            cnt+=d[i];
        }
        else
        {
            v=c;
            ans+=2*cnt;
            i--;
        }
    }
    ans+=a[n];
    printf("%lld\n",ans);
    return 0;
}

题目3 : 浇花问题2

描述

小Ho在一条小路上种植了一排月季,总共有N株。这条小路的一端是一个水龙头。N株月季距离水龙头由近到远的距离依次是A1, A2, ... AN,每天需要浇水的量依次是B1, B2, ... BN。  

小Ho有一个水壶,假设容量是C。他从水龙头出发,拎着灌满的水壶,依次去浇灌第1株、第2株、第3株…… 如果浇完第K株时,小Ho发现水壶中剩余的水量不足以浇灌第K+1株,他会回到水龙头处,将水壶灌满水,再依次去浇灌第K+1株、第K+2株……

最终小Ho浇完第N株之后,回到水龙头处。小Ho比较懒,他希望自己总计行走的距离不超过一个给定的整数L,那么水壶的容量C至少是多少?

输入

第一行包含两个整数N和L。  

第二行包含N个整数A1, A2, ... AN。  

第三行包含N个整数B1, B2, ... BN。  

1 <= N <= 100000  

1 <= Ai <= 1000000  

1 <= Bi <= 10000  

2 * AN <= L <= 1012

输出

一个整数代表答案

样例输入

3 17  
1 3 5  
5 4 5

样例输出

9

题意:看题

思路:二分加模拟(这是在上一题的基础上加深的题目注意二分答案的最小值是给出序列中的最大值,不然模拟会超时)

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long

using namespace std;

const int maxn=1e5+100;
LL a[maxn],b[maxn],d[maxn];
int n;
LL L;
bool check(LL x)
{
    LL ans=0,cnt=0,v=x;
    for(int i=1;i<=n;i++)
    {
        if(v>=b[i])
        {
            v-=b[i];
            ans+=d[i];
            cnt+=d[i];
        }
        else
        {
            v=x;
            ans+=2*cnt;
            i--;
        }
        if(ans>L)
            return false;
    }
    ans+=a[n];
    //cout<<ans<<" "<<L<<endl;
    return ans<=L;
}
int main()
{
    scanf("%d%lld",&n,&L);
    LL sum=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        d[i]=a[i]-a[i-1];
    }
    LL l=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&b[i]);
        sum+=b[i];
        l=max(b[i],l);
    }
    LL r=sum+1;
    l--;
    LL mid;
    while((r-l)>1)
    {
        mid=(l+r)/2;
        //cout<<mid<<endl;
        //cout<<check(mid)<<endl;
        if(check(mid))
        {
            r=mid;
        }
        else
        {
            l=mid;
        }
        //cout<<l<<" "
    }
    printf("%lld\n",r);
}

题目2 : 连续整数列

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi有N张卡片,其中第i张卡片上写着一个整数Ai。现在小Hi希望这N张卡片上的数字能组成一个长度为N连续整数列,则他至少需要改变多少张卡片上的整数?

输入

第一行包含一个整数N。  

第二行包含N个整数A1, A2, ... AN.  

1 <= N <= 100000  

1 <= Ai <= 1000000

输出

一个整数代表答案

样例输入

5  
1 1 9 8 7

样例输出

2

题意:给你n个数看最少改几个数字,这n个数可以组成一个连续的序列。

思路:统计那些数出现然后再暴力枚举注意n可能比出现的数大所以要去全部枚举,不然会出错。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
#define INF 0x3f3f3f3f

using namespace std;
const int maxn=1e6+100;
int dp[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    int Max=-1;
    for(int i=1;i<=n;i++)
    {
        int a;
        scanf("%d",&a);
        dp[a]=1;
        Max=max(Max,a);
    }
    for(int i=1;i<=Max;i++)
    {
        dp[i]+=dp[i-1];
    }
    int ans=INF;
    for(int i=0;i<=Max;i++)
    {
        int j=i+n;
        if(j>Max)
            j=Max;
        ans=min(n-(dp[j]-dp[i]),ans);
    }
    printf("%d\n",ans);
    return 0;
}

 

题目4 : 还原BST

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi有一棵二叉搜索树(BST)。小Ho想知道这颗树的结构。

小Hi为了考验一下小Ho,只告诉他这棵BST的层序遍历(从上到下、从左到右)序列。  

例如如下的BST,层序遍历序列是:5, 3, 10, 1, 4, 7

              5
            /   \
           3     10
          / \   /
         1   4 7

输入

第一行包含一个整数N,代表BST的节点数目。  

第二行包含N个整数A1, A2, ... AN,代表BST的层序遍历序列。  

1 <= N <= 100000  

1 <= Ai <= 1000000

输入保证Ai两两不同且有唯一解

输出

输出N个整数,依次代表A1, A2, ... AN的父节点是多少。对于根节点输出0。

样例输入

6  
5 3 10 1 4 7

样例输出

0 5 5 3 3 10

题意:看题就好。

思路:因为给出的是层次遍历的顺序所以跟是第一个然后小的在左边,大的在右边。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#define LL long long

using namespace std;
const int maxn=1e5+100;
struct node
{
    int x,id;
};
vector<node>gg;
int fa[maxn];
void dfs(vector<node>& gt,int f)
{
    fa[gt[0].id]=f;
    vector<node>gg1,gg2;
    for(int i=1;i<gt.size();i++)
    {
        if(gt[i].x<gt[0].x)
        {
            gg1.push_back(gt[i]);
        }
        else
        {
            gg2.push_back(gt[i]);
        }
    }
    if(gg1.size()>0)
        dfs(gg1,gt[0].x);
    if(gg2.size()>0)
        dfs(gg2,gt[0].x);
    return ;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        node a;
        scanf("%d",&a.x);
        a.id=i+1;
        gg.push_back(a);
    }
    dfs(gg,0);
    for(int i=1;i<=n;i++)
    {
        if(i!=n)
        {
            printf("%d ",fa[i]);
        }
        else
        {
            printf("%d\n",fa[i]);
        }
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值