Codeforces Round #521 (Div. 3) ABCDEF1F2总结

要是C没挂终测,我这场就。。。没有什么要是。C题读错题了。终测前6道rk47,终测完5道rk140。虽然上了86分,但是心里还是很sad。。。

A题:

没什么好说的。统计1~k的奇数和偶数个数。答案就是n*((k+1)/2)-(m*(k/2))。

B题:

考虑贪心,每次出现“101”这种情况我们就把后面的1改成0。这样10101这种情况我们只需要改一个,肯定是最优的。

C题:

这道题我居然读错了题  WAWAWA

就是对每一个a[i],若删除a[i]后,剩下的数的和为剩下的数中的最大数的两倍。则输出下标i。

对数组排序后,显然a[1]~a[n-1]的情况都是a[n]为最大。所以特判一下a[n]的情况删a[n-1]就可以了。

D题:给你n个数字,

每一轮删除k个数字(每一轮都删除一样的数字),求进行轮数最多的情况下每一轮删哪k个数。

用数组记录每个数字出现的次数。然后二分进行的轮数。注意输出的时候每个数字输出   次数/轮数  向下取整 次。

E题:

给你n道题。每道题的难度规定一个数字。

任意两场比赛的题目难度不能有相同的,但是每一场的题目难度必须相同。第一场如果是k道题,那么第i场就是k*(2的(i-1)次方)道题。

求题数最多的情况下,能用多少道题举办比赛。(并不一定举办的场数最多)

由于与数字大小无关,我们进行离散化,统计每个数字出现的次数并存到数组中。

排序。枚举第一场是几道题(1~出现次数最多的数字的次数)

然后用一个变量l记录>=当前需要数量的最小下标,暴力找能用多少题(在第一场的题数确定的情况下)。显然可以二分,又由于每次题数都要*2,所以总复杂度不会超过O(n*logn*logn)。

F1题:

n件物品,每种价值为a[i],你只能买正好x件,连续k件物品中必买一件。问你最多买多少价值的衣服。不满足条件输出-1。

显然可以暴力三维dp[i][j][k],表示前i天买了j件上一件是第k天买的最大价值。注意初始化的细节。

F2题:

显然上述思路中,确定买了j件之后,前i天能获得的最大价值是递增的。然后用一个单调队列压缩掉第三维,只要队头和当前天数i超过x天就出队即可。比赛的时候来不及写了。赛后1A。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=5010;
const ll mo=1e9+7;
int n,m,k,q,x;
ll a[maxn],dp[maxn][maxn];
ll sum;
ll c[maxn];
ll ans,ct,cnt,tmp,flag;
char s[maxn];
pair<int,ll>st[maxn*2];
int main()
{
    ll T,cas=1;
    //scanf("%d",&T);
    //while(T--)
    {
        scanf("%d%d%d",&n,&k,&x);
        memset(dp,-1,sizeof(dp));
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        dp[0][0]=0;
        for(int z=1;z<=x;z++){
            int aa=0,bb=-1;
            st[++bb]=make_pair(0,dp[z-1][0]);
            for(int i=1;i<=n;i++)
            {
                int t=max(0,i-k);
                while(aa<=bb&&st[aa].first<t) aa++;
                if(aa>bb) continue;
                ll rr=st[aa].second;
                if(rr>=0) dp[z][i]=rr+a[i];
                while(aa<=bb&&st[bb].second<=dp[z-1][i]) bb--;
                st[++bb]=make_pair(i,dp[z-1][i]);
            }
        }
        ans=-1;
        for(int i=max(0,n-k+1);i<=n;i++)
        ans=max(ans,dp[x][i]);
        printf("%lld\n",ans);
      //  if(flag) puts("Yes"); else puts("No");
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值