zoukankan      html  css  js  c++  java
  • CF794E Choosing Carrot

    题解:

    我们可以先考虑不进行 (k) 操作的情况

    ​ 当取完的时候,因为最优(B都可以通过他的 (dfrac{n}2-1) 次机会取走,所以只有 (mid)(mid+1) 对于B来说是无能为力的),肯定是剩下中间的几个

    ​ 然后由A选择小的那个,剩下大的,则有两种情况:

    [ans=egin{cases}max(a[mid],a[mid+1])~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~n为偶数\max(min(a[mid],a[mid-1]),min(a[mid],a[mid+1]))~~~n为奇数end{cases} ]

    然后考虑进行 (k) 操作

    ​ 当A多吃,只有 (mid) 会被影响,发生变化,而每个 (iin [1,k-2]) 是由 (i+2) 转移过来的,三种可能:

    要么左右各拿一个 (mid) 不变,要么左边或者右边拿俩 (mid) 变化,而我们考虑奇偶即可,左右拿俩可以合并到一个数组,但是如果要求左右拿俩的情况,则需要用到动态规划

    ​ 设 (h[i]) 为偶数个数当 (i) 为中点时最大值, (g[i]) 为奇数个数当 (i) 为中点时最大值,可得方程:

    [h[min(i,n-i)]=max(h[min(i,n-i)],max(a[i],a[i+1]))\ g[min(i-1,n-i)]=max(g[min(i-1,n-i)],max(min(a[i],a[i-1]),min(a[i],a[i+1]))) ]

    ​ 因为可以类比,所以这里的转移用到了上面不进行 (k) 操作时的转移, (i/i-1)(n-i) 代表左拿还是右拿。

    所以,设 (ans[i]) 为剩下 (i) 个元素能取到的最大值,转移方程为:

    [ans[2*i]=max(ans[2*i+2],h[i])\ ans[2*i+1]=max(ans[2*i+3],g[i]) ]

    最后倒序输出,时间复杂度 (O(n))

    代码

    #include <cstdio>
    #include <iostream>
    
    using namespace std;
    const int MAXN=300005;
    int n,a[MAXN],h[MAXN],g[MAXN],ans[MAXN];
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            ans[1]=max(ans[1],a[i]);
        }
        for(int i=1;i<n;i++) h[min(i,n-i)]=max(h[min(i,n-i)],max(a[i],a[i+1]));//代表偶数下的最值 
        for(int i=2;i<n;i++) g[min(i-1,n-i)]=max(g[min(i-1,n-i)],max(min(a[i-1],a[i]),min(a[i],a[i+1])));//代表奇数下的最值 
        for(int i=n/2;i>=1;i--)
        {
            ans[i<<1]=max(ans[(i+1)<<1],h[i]);
            ans[i<<1|1]=max(ans[(i+1)<<1|1],g[i]);
        }
        for(int i=n;i>=1;i--)
            printf("%d ",ans[i]);
    }
    
  • 相关阅读:
    组合模式扩展,有选择的递归
    SQL分页查询【转】
    facade外观模式
    C#:几种数据库的大数据批量插入 faib
    装饰模式的扩展
    yeild之我理解
    数据库操作 sqlserver查询存储过程+分页
    SQL Server 索引结构及其使用(二)[转]
    SQL索引使用初步,(转)
    解决多集成,多子类,扩展等 装饰模式
  • 原文地址:https://www.cnblogs.com/jasony/p/13419072.html
Copyright © 2011-2022 走看看