洛谷P3129 [USACO15DEC]高低卡(白金)High Card Low Card (Platinum)

https://daniu.luogu.org/problem/show?pid=3129
很好的一道题目
题解:

这道贪心还真的有点把我6到了。。。
如果按照田忌赛马的逻辑之类的
很容易想到 要大的赢得时候 选一个刚好比他大一点的就好 小的时候同理 选一个刚好小一点的
那么我们用set前后搞一下 front[i]就是大的赢 1到i赢最多的盘数 behind[i]同理 从后往前 n到i 小的赢
答案就max(f[i]+g[i+1]) 然而我知道你想问我选重复怎么办?
这里有个证明: 如果有一个数a用了两次 那么假设没用的那个数b < a 那么在较小赢时候可以替换a 反之亦然
刷访问量走起…http://blog.csdn.net/cgh_andy/article/details/53011315;

真的很牛逼,我当然想到了可以通过前后缀数组做,但是重复的现象是必然的,没想到尽然是不影响的;
真的是太菜了

#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=1e5+5;
int a[N],f[N],F[N],fa[N],Fa[N];
int n,m,ans;
int get1(int x){return fa[x]==-1?x:fa[x]=get1(fa[x]);}
int get2(int x){return Fa[x]==-1?x:Fa[x]=get2(Fa[x]);}
int main()
{
    scanf("%d",&n);
    memset(fa,-1,sizeof fa);
    memset(Fa,-1,sizeof Fa);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        fa[a[i]]=a[i]+1;
        Fa[a[i]]=a[i]-1;
    }
    for(int i=1;i<=n;i++){
        f[i]=f[i-1];
        int x=get1(a[i]+1);
        if(x==n*2+1)x==get1(1);
        if(x==n*2+1)continue;
        if(x>a[i])f[i]++;
        fa[x]=get1(x+1);
    }
    for(int i=n;i>=1;i--){
        F[i]=F[i+1];
        int x=get2(a[i]-1);
        if(x==0)x==get2(n);
        if(x==0)continue;
        if(x<a[i])F[i]++;
        Fa[x]=get2(x-1);
    }
    for(int i=0;i<=n;i++)ans=max(ans,f[i]+F[i+1]);
    printf("%d",ans);    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值