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

来源:互联网 发布:杀肖数据统计资料区 编辑:程序博客网 时间:2024/04/30 18:02

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 longusing 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);    }
原创粉丝点击