11.5 | 学习笔记

记录今天A的两个题

https://codeforces.com/contest/1395/problem/D

给你n个数字,当某一个n大于零的时候,他后面的d个数字都会变成0,问怎样排布能让数列总和最大

要尽可能大,思路是首先将n分为合法和不合法两类,

在Du被禁言的时候,不管取多少后面的d天都被禁言了,那为了给和贡献最大,破罐子破摔取最大的,

在其他可以畅所欲言的时候,为了给和贡献最大,就要在违法的边缘试探,同样尽量取合法值里面最大的,

我的想法是枚举可以被禁言的次数,注意这里要上取整,同时最后一天必然被禁言,否则的话同等条件下,在最后一次被禁言的那天到最后一天就对和没有贡献,那莫不如先让他前几天贡献,最后一天禁言,注意这里的表达式,n-(i-1)*(d+1)-1(最后那个1就是最后一次被禁言)那么这里i=0时n-1=-1显然是没有意义的,所以可以在循环外面将ans赋值成禁言0次的情况,但是需要注意,这里的ans并不是答案,只是一个下限,因为大多数情况下不能保证每个数都比m小,加这个是为了防止出现这种特殊情况,注意前缀和的使用可以降低求和的时间复杂度:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long int ll;
ll d,n,m,tmp,cnt,x,y,res,ans;
ll ud[maxn],ov[maxn];

int main()
{
    cin>>n>>d>>m;
    d++;// 由于d后来每次出现都是d+1,所以一开始直接++
    for(int i=0;i<n;i++)
    {
        cin>>tmp;
        if(tmp>m)ov[++x]=tmp; // 不合法类
        else ud[++y]=tmp; // 合法类
    }
    cnt=ceil(1.0*n/d);
    sort(ov+1,ov+x+1,greater<ll>()); // 降序,下同
    sort(ud+1,ud+y+1,greater<ll>());
    for(int i=1;i<=x;i++)
        ov[i]+=ov[i-1];
    for(int i=1;i<=y;i++)
        ud[i]+=ud[i-1];
    ans=ud[y];
    for(int i=1;i<=cnt;i++)
    {
        res=ov[i];
        res+=ud[min(y,n-(i-1)*d-1)];
        if(res>ans)ans=res;
    }
    cout<<ans<<endl;
    return 0;
}

 

https://codeforces.com/contest/1443/problem/D

这题一开始不会,某北极熊给了很好的思路,抽象为判断能否将给定序列拆分成一个非递增序列和非递减序列,

假设A为递减序列,B为递增序列,那么为了尽可能满足条件,每次尽量给A多分一部分,给B少分一部分,这样才不会给后来项的拆分添麻烦

(通俗来讲就是我前面的项为了满足条件已经很够意思了,你后面的再不行就直接判断不合法滚粗)

每次输入一个数,判断这个数和上次剩下的数的关系,如果小于直接判断不合法;

如果合法,先给B预留出一部分,这部分要尽可能小,也就是给A留的尽可能大,但是问题在可能B可以了但是剩下的给A的太多了导致A不能递减,那就在满足A的条件下给B多分点,上图:

 

 以第二列为例,刚才给B分的是0,A是5,首先看能不能再给B分0,这时候发现A分了7,大于5不合法,所以只能给A分5,这样B不得已增到2,

同理第三列,能不能给B分2,发现这样的话A分1,合理,依此类推...

所以到后来甚至数组都不用存了,直接循环:

#include <bits/stdc++.h>
using namespace std;
int t,n,gap,lef,now,flag; // gap上次减掉的,lef上次剩下的

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>gap;
        flag=1;lef=0;
        while(--n)
        {
            cin>>now;
            if(now<lef)
                flag=0;
            else
            {
                gap=min(gap,now-lef);
                lef=now-gap;
            }
        }
        cout<<(flag?"Yes\n":"No\n");
    }
    return 0;
}

 

posted @ 2020-11-05 23:51  MissCold  阅读(84)  评论(0编辑  收藏  举报