[NOIP2016 提高组] 天天爱跑步

题面,题解就不打了,写的较好的题解

主要是借这个题说一下如何正确的思考出来一道题:

首先样例肯定要模,在模的时候就是构建思路的过程,当然一般的小样例无论什么方法都可以得出答案(spj),能过正确的理解题面就行;

然后我们就可以顺着方案A想,看看是否有漏洞(反例)、复杂度(以这个题来说:每个人(跑m次)一遍一遍统计很好想出来,但稍微一分析就知道并不可行,但此时我们还不能轻易放弃它,想想怎么优化,深挖它的本质)、实现难度(得分效果);

如果不可行——转化思路,并不是换另一种等效做法!既然一个一个统计不行,就从整体着手;

如果可行(无论哪个方案):对于图的问题最好在纸上多动笔画画,推出一点眉目来就想想有没有不全or重复的情况;

分析的差不多了在考虑实现(多注意注意细节:如果不是一模一样就别先复制再改,容易少改某个地方;long long),最好要一气呵成。

既然是题解,怎么能没有代码呢?moo~~
 #include<bits/stdc++.h>
#define Bessie moo~~
#define int long long
using namespace std;
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
int read(){
    int A=0,FL=1;
    char C=getchar();
    while(C<'0'||C>'9')FL = C == '-' ? -1:1,C=getchar();
    while(C>='0'&&C<='9')A=(A<<3)+(A*2)+(C^'0'),C=getchar();
    return A*FL;
}
int T;
const int INF=1e9+7,N=5e3+5;
int n,m;
int a[N];
int f[N],zs[N][N],t[N];//众数的频数
int ans;
bool il(int x,int y){
    if(x>y)return 1;
    return zs[x][y]<=((y-x+1)>>1);
}
signed main(){
    T=read();
    while(T--){
        n=read();
        ans=0;
        for(int i=1;i<=n;i++){
            a[i]=read();
            f[i]=0;
        }
        for(int i=1;i<=n;i++){
            int tmp=0;
            for(int j=i;j<=n;j++){
                t[a[j]]++;
                if(t[a[j]]>t[tmp])tmp=a[j];
                zs[i][j]=t[tmp];
            }
            for(int j=i;j<=n;j++){
                t[a[j]]=0;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                if(j>1&&a[j-1]!=a[i])continue;
                if(((i-1)-j+1)&1)continue;//[j,i)长度为奇数不能完全删除 
                if(il(j,i-1))f[i]=max(f[i],f[j-1]+1);
            }
            if(f[i]==0)f[i]=-INF;
            // printf("f[%lld] = %lld\n",i,f[i]);
        }
        for(int i=1;i<=n;i++){
            if((n-(i+1)+1)%2==0&&il(i+1,n))
            ans=max(ans,f[i]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2022-06-24 18:59  Creator_157  阅读(44)  评论(0编辑  收藏  举报