zoukankan      html  css  js  c++  java
  • 【2019.10.4】NOIP2019模拟训练题

    总结

    T1 想的时间太久了(1h30min),思路是完全正确的,但对dp本身理解和练习还不够就没打,时间复杂度倒是分析出来了。

    T2 贪心(我打的更像模拟)就直接过了,没用二分。30min左右就打完了。

    T3 10分应该能拿到。卡在T1上所以完全抛掉了。

    总的来说,一眼就可以看出哪些题比较可做,当然还是要花点时间稍微分析一下,以防能做的题以为不能做。先把可做的题分析好,打出来,不可做的题打打暴力拿一些部分分。

    T1.

    区间dp,破环成链是基本操作,预处理g数组。

    代码:

    #include<bits/stdc++.h>
    #define For(i,l,r) for(int i=l;i<=r;i++)
    #define DFor(i,r,l) for(int i=r;i>=l;i--)
    #define ll long long
    #define ri register int
    using namespace std;
    const int M=666;
    ll n,a[M],f[M][M],g[M][M],ans;
    bool b[M];
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline void sets(){
        For(i,1,n) g[i][i]=1;
        For(i,1,n-1){
            memset(b,0,sizeof(b));
            b[a[i]]=1;
            For(j,i+1,n){
                if(b[a[j]]) g[i][j]=g[i][j-1];
                else b[a[j]]=1,g[i][j]=g[i][j-1]+1;
            }
        }
    }
    int main(){
        freopen("merge.in","r",stdin);
        freopen("merge.out","w",stdout);
        n=read();
        For(i,1,n) a[i]=read(),a[n+i]=a[i];
        n<<=1;
        sets();
        DFor(i,n-1,1){
            For(j,i+1,n){
                For(k,i,j-1){
                    f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+g[i][k]*g[k+1][j]);    
                }
            }
        }
        For(i,1,n) ans=max(ans,f[i][i+(n>>1)-1]);
        printf("%lld",ans);
        return 0;
    }
    View Code

    T2.

    (拿完部分分我就跑)40分的特殊点好像很好拿的样子→(突然发现)Ci=0的情况考虑下Ci非零会被淹死不就可以了吗,时间复杂度不会算,80分总是有的吧→(考完后)听说要用二分完了我挂了→(看到成绩)AK了??

    直接丢代码:

    #include<bits/stdc++.h>
    #define For(i,l,r) for(int i=l;i<=r;i++)
    #define DFor(i,r,l) for(int i=r;i>=l;i--)
    #define ll long long
    #define ri register int
    using namespace std;
    const int M=1e5+5;
    ll n,l,c[M],ans,wall,ea[M],cnt=1;
    bool fb,fc;
    struct node{
        ll a,b,u;
    }e[M];
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline ll cmpa(node x,node y) {return x.a>y.a;}
    inline ll cmpp(node x,node y) {return x.u==y.u?x.a<y.a:x.u>y.u;}
    inline ll cmpea(ll x,ll y) {return x>y;}
    int main(){
        freopen("climb.in","r",stdin);
        freopen("climb.out","w",stdout);
        n=read(),l=read();
        For(i,1,n){
            e[i].a=read();e[i].b=read();e[i].u=e[i].a-e[i].b;
            ea[i]=e[i].a;
            if(e[i].b) fb=1;
        }
        For(i,1,n){
            c[i]=read();
            if(c[i]) fc=1;
        }
        if(!fb){//no fall
            sort(e+1,e+n+1,cmpa);
            For(i,1,n){
                ans+=e[i].a;
                wall+=c[i];
                if(ans<0){
                    printf("-1");
                    return 0;
                }
                if(ans>=l){
                    printf("%d",i);
                    return 0;
                }
                if(ans<=wall){
                    printf("-1");
                    return 0;
                }
            }
            printf("-1");
            return 0;
        }
        if(!fc){//no wall
            sort(e+1,e+n+1,cmpp);
            sort(ea+1,ea+n+1,cmpea);
            For(i,1,n){
                if(ans<0){
                    printf("-1");
                    return 0;
                }
                if(ans+ea[1]>=l){
                    printf("%d",i);
                    return 0;
                }
                ans+=e[i].u;
                if(ea[1]==e[i].a){
                    ea[1]=ea[++cnt];
                }
            }
            printf("-1");
            return 0;
        }
        sort(e+1,e+n+1,cmpp);
        sort(ea+1,ea+n+1,cmpea);
        For(i,1,n){
            if(ans+ea[1]>=l){
                printf("%d",i);
                return 0;
            }
            ans+=e[i].u;
            wall+=c[i];
            if(ans<=wall){
                printf("-1");
                return 0;
            }
            if(ans<0){
                printf("-1");
                return 0;
            }
            if(ea[1]==e[i].a){
                ea[1]=ea[++cnt];
            }
        }
        printf("-1");
        return 0;
    }
    View Code
  • 相关阅读:
    .NET基础——数组
    .NET基础——循环、枚举
    .NET基础——运算符
    .NET基础——基本概念
    面向对象基础——结构体
    面向对象基础——静态成员、静态类
    面向对象基础——基本概念
    接口 与 抽象类
    委托与事件——事件
    委托与事件——委托
  • 原文地址:https://www.cnblogs.com/jian-song/p/11622101.html
Copyright © 2011-2022 走看看