西电第一周 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\n",ans[i]);
        }
        int sum=(n*(n-1))/2;
        for(int i=1;i<=n-1;i++)
        {
            if(sum+1-k<=ans[i])
            {
                printf("%d\n",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\n",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\n",l,r);
            long long mid=(l+r)>>1;
            if(check(mid)){
            r=mid-1;
            }
            else
            l=mid+1;
        }
        printf("%lld\n",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\n"); continue; } printf("%d\n",l+1); } }

猜你喜欢

转载自www.cnblogs.com/SoniciSika/p/9034203.html