zoukankan      html  css  js  c++  java
  • 西电第一周 b,d,j,m题题解

    西电第一周 b,d,j,m题题解

    先碎碎念

    不得不说已经很久很久没有写题解了,现在想想也的确欠了好多该写的题解没写,并不是说自己不想写还是怎样,这样说实际上对我不公正,因为我个人是很喜欢写题解的,或者说我个人实际上是很喜欢写点什么的。若要较为准确地把握其原因的话,我想,可以做这样的表述:自己太过于投入,而忘记了从更加系统化的层面把握事情

    那么,开始吧。

    对于b题来说

    先对牌排序,发现这样的单调规律:最小的牌和其余n-1个牌搭配的时候答案是最小的牌,倒数第二小的牌和其余n-2个牌搭配的时候答案是倒数第二小的牌...以此类推。可以发现是一个等差数列,答案为i的时候对应n-i,我们想知道第k大分值,也就是第(n*(n-1)/2+1-k)小分值,设ans[i]为拿到第i小的牌时总共是多少种情况(显然,ans[i]等于1-i的等差数列之和)。

    当(n*(n-1)/2+1-k)第一次小于等于ans[i]时 输出i即可。
    

    对于d题来说

    发现是个等比数列,第i个位置对应的桃子为2^(i-1),同样求和,当猴子妈妈准备的桃子数第一次大于第i个位置时的和时,说明猴子妈妈的桃子不够了,后面的小猴子没桃子吃了=。=,那么最终答案一定是第i-1个位置的和第i个位置的之间的最大值。

    j题的话

    我是用二分答案最短时间,假设说时间x内能完成,也就意味着对于每道题来说,一定已经被完成了x分钟,并且每分钟可以选择一道题完成k分钟嘛,我们就从头开始枚举,哪一道题完成x分钟不够,我们就一定要在他上面花费更多的时间去完成,当然未必是1天,可能是很多天,具体计算方法是

    (((a[i]-temx)%k==0)?((a[i]-temx)/k):((a[i]-temx)/k+1));
    

    temx即为x,a[i]即为第i道题一共所需时间。

    m题呢

    m题真是很好的一道题=。=
    先是写二分答案和线段树,狂tle(线段树求和的复杂度无论如何都是相当不容忽视的啊=。=)
    不过其实把线段树换成前缀数组就好了,反正无论如何也用不到线段树的其他功能,仅仅是区间求和的话前缀数组就能很好的完成。
    当然,尺取法也可以,不过我目前只是通过这一道题稍微知道有尺取法这个算法,具体还不太理解,也用不好,还需要多做几道题理解一下。

    完整代码

    B

    #include<bits/stdc++.h>
    using namespace std;
    int t,n,k;
    int a[2505];
    int ans[2505];
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d %d",&n,&k);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
            }
            sort(a+1,a+1+n);
            memset(ans,0,sizeof(ans));
            for(int i=1;i<=n;i++)
            {
                ans[i]=ans[i-1]+n-i;
               // printf("A %d
    ",ans[i]);
            }
            int sum=(n*(n-1))/2;
            for(int i=1;i<=n-1;i++)
            {
                if(sum+1-k<=ans[i])
                {
                    printf("%d
    ",a[i]);
                    break;
                }
            }
        }
    }
    
    

    D题就不贴了。=。=
    J

    #include<bits/stdc++.h>
    #define MAXN 100005
    using namespace std;
    int t,n;
    long long tem,k;
    long long a[MAXN];
    int check(long long x)
    {
        long long temx=x;
        for(int i=1;i<=n;i++)
        {
            if(x<0)
            {
                return 0;
            }
            if((a[i]-temx<=0)&&(x>=0))
            {
              //  printf("%lld %lld
    ",a[i],x);
                return 1;
            }
            x-=(((a[i]-temx)%k==0)?((a[i]-temx)/k):((a[i]-temx)/k+1));
        }
        if(x>=0)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    //
    bool cmp(long long l1,long long l2)
    {
        return l1>l2;
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
            }
            scanf("%lld",&k);
            sort(a+1,a+1+n,cmp);
            long long r=1000000000,l=1;
            while(l<=r)
            {
                //printf("%lld %lld
    ",l,r);
                long long mid=(l+r)>>1;
                if(check(mid)){
                r=mid-1;
                }
                else
                l=mid+1;
            }
            printf("%lld
    ",l);
        }
    }
    
    

    M

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int MAXN = 100005;
    int t,n;
    long long m;
    long long pre[MAXN];
    int a[MAXN];
    int check(int x)
    {
        for(int i=1;i<=n-x;i++)
        {
            if(pre[i+x]-pre[i-1]>=m)
            {
                return 1;
            }
        }
        return 0;
    }
    int main()
    {
        scanf("%lld",&t);
        while(t--)
        {
            scanf("%d %lld",&n,&m);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                pre[i]=pre[i-1]+a[i];
            }
            int r=n,l=0;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(check(mid)){
                r=mid-1;
                }
                else
                l=mid+1;
            }
            if(r+1>n)
            {
                printf("0
    ");
                continue;
            }
            printf("%d
    ",l+1);
        }
    }
    
  • 相关阅读:
    盒子!盒子!盒子!
    常用图片加链接文字加链接代码
    滚动跑马灯标记marquee实用代码
    版权所有LIKEWING_柳我借地存个图学习一下
    一个用CSS制作的表单样式
    一段代码学会CSS交集选择器和并集选择器
    菜鸟关于CSS的一点思考
    后代选择器的范例
    利用JavaScript脚本改中的颜色
    JavaScript:在线五子棋盘
  • 原文地址:https://www.cnblogs.com/SoniciSika/p/9034203.html
Copyright © 2011-2022 走看看