• 校内集训20180918


    $T1:$(Loj507

    $N$张扑克牌依次添加,花色为$a_i$,点数为$b_i$,每添加一张牌$i$可以选择另一张花色相同的牌$j$并把$j,j+1,ldots,i$的牌移走,产生这些牌点数之和的贡献,问最多

    产生多少贡献。

    $Nleq 2 imes 10^6$,时限$600ms$。

    题解:

    $O(N^2)DP$不是重点,重点是如何优化$dp[i]=max(dp[i],dp[j-1]+sum[i]-sum[j-1]|a_j==a_i)$这个方程。

    可以发现$dp[i]=sum[i]+max{dp[j-1]-sum[j-1]|aj==ai}$,那么我们考虑对每个颜色维护当前最大的$dp[j-1]-sum[j-1]$,即可$O(1)$转移。

    傻逼题$100pts$没有挂。

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    #define MAXN 1000005
    #define MAXM 500005
    #define INF 1LL<<50
    #define ll long long
    
    ll dp[MAXN],c[MAXN],v[MAXN];
    ll maxn[MAXN],sum[MAXN];
    inline ll read(){
        ll x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar())
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar())
            x=x*10+c-'0';
        return x*f;
    }
    
    int main(){
        ll N=read(),K=read();
        for(ll i=1;i<=N;i++) c[i]=read();
        for(ll i=1;i<=K;i++) maxn[i]=-INF;
        for(ll i=1;i<=N;i++) v[i]=read(),sum[i]=sum[i-1]+v[i];
        for(ll i=1;i<=N;i++){
            dp[i]=max(dp[i-1],sum[i]+maxn[c[i]]);
            /*for(ll j=1;j<i;j++)
                if(c[j]==c[i]){
                    dp[i]=max(dp[i],sum[i]+dp[j-1]-sum[j-1]);
                }*/
            maxn[c[i]]=max(maxn[c[i]],dp[i-1]-sum[i-1]);
        }
        printf("%lld
    ",dp[N]);
        return 0;
    }
    /*
    
    18 5
    5 2 3 5 1 3 5 2 1 4 2 4 5 4 1 1 1 5
    8 2 7 6 10 8 10 9 10 2 4 7 7 7 7 9 7 3
    */

    $T2:$(Loj2279

    给定$N$个年份和该年的降水量,再给定$Q$个问题,每个问题由$(Y,X)$表示,判断“$X$年是$Y$年以来降水量最多的”这句话是否正确。

    注意$Ysim X$之间的降水量不一定是给定的,如果不能判断是否正确则输出不确定。

    $Nleq 50000$,空间限制$64MB$。

    题解:

    如果没有不确定这个选项那么就是一个$ST$表模板。

    然而现在要写巨大的一个分类讨论。

    理论上来说只需要在确定的基础上判断若$Ysim X$中间有任意一点未知则不确定。

    然而我好像写丑了。

    码农题$0pts$喜闻乐见。

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    #define MAXN 50005
    #define MAXM 500005
    #define INF 0x7fffffff
    #define ll long long
    
    int year[MAXN],level[MAXN];
    int N,f[MAXN][17],log2[MAXN];
    inline int read(){
        int x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar())
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar())
            x=x*10+c-'0';
        return x*f;
    }
    
    void init(){
        log2[1]=0;
        for(int i=2;i<=MAXN;i++) log2[i]=log2[i>>1]+1;
        for(int i=1;i<=N;i++) f[i][0]=level[i];
        for(int j=1;j<17;j++)
            for(int i=1;i+(1<<j-1)<=N;i++)
                f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
        return;    
    }
    
    int main(){
        //freopen("1 (1).in","r",stdin);
        //freopen("2.ans","w",stdout);
        N=read();
        for(int i=1;i<=N;i++) year[i]=read(),level[i]=read();
        init(); int M=read();
        for(int i=1;i<=M;i++){
            int Y=read(),X=read();
            if(Y>=X){
                cout<<"false"<<endl;
                continue;
            }
            int t1=lower_bound(year+1,year+1+N,Y)-year;
            int t2=lower_bound(year+1,year+1+N,X)-year;
            //cout<<t1<<":"<<t2<<endl;
            if(year[t1]!=Y && year[t2]!=X){
                cout<<"maybe"<<endl;
                continue;
            }
            else if(year[t1]!=Y && year[t2]==X){
                if(t1==t2){
                    cout<<"maybe"<<endl;
                    continue;
                }
                else{
                    t2--;int k=log2[t2-t1+1];
                    int maxn=max(f[t1][k],f[t2-(1<<k)+1][k]);
                    if(maxn>=level[t2+1]) cout<<"false"<<endl;
                    else cout<<"maybe"<<endl;
                    continue;
                }
            }
            else if(year[t2]!=X && year[t1]==Y){
                if(t1+1==t2){
                    cout<<"maybe"<<endl;
                    continue;
                }
                else{
                    t2--;t1++;int k=log2[t2-t1+1];
                    int maxn=max(f[t1][k],f[t2-(1<<k)+1][k]);
                    if(maxn>=level[t1-1]) cout<<"false"<<endl;
                    else cout<<"maybe"<<endl;
                    continue;
                }
            }
            else{
                if(t1+1==t2){
                    if(level[t2]<=level[t1]){
                        if(t2-t1+1==X-Y+1) cout<<"true"<<endl;
                        else cout<<"maybe"<<endl;
                    }
                    else cout<<"false"<<endl;
                    continue;
                }
                else{
                    t2--;t1++;int k=log2[t2-t1+1];
                    int maxn=max(f[t1][k],f[t2-(1<<k)+1][k]);
                    if(maxn>=level[t1-1] || maxn>=level[t2+1] || level[t2+1]>level[t1-1]) cout<<"false"<<endl;
                    else if(t2-t1+3==X-Y+1) cout<<"true"<<endl;
                    else cout<<"maybe"<<endl;
                    continue;
                }
            }
        }
        return 0;
    }

    $T3:$(Loj2332

    给你$i$个数,若$A_igeq A_{i-1}$则$T_i=-(A_i-A_{i-1}) imes S$,否则$T_i=-(A_i-A_{i-1}) imes T$,有$M$组更新$(L,R)$将$[L,R]$区间内的$A_i ightarrow A_{i+v}$。

    每次更新后输出$ans=sum T_i$的值。

    $Nleq 2 imes 10^5$,时限$200ms$。

    题解:

    考场上一直在想怎么把线段树优化过时限。于是$0pts$。

    后来考完一想,$T$每次更新只需要更俩数,$ans$只需要把这更新的俩数值加上再减去原值就行了。

    在线求助智力康复学校。

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    #define MAXN 200005
    #define MAXM 500005
    #define INF 0x7fffffff
    #define ll long long
    
    ll N,Q,S,T,A[MAXN],B[MAXN];
    inline ll read(){
        ll x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar())
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar())
            x=x*10+c-'0';
        return x*f;
    }
    
    ll calc(ll x){return x>0?-x*S:-x*T;}
    
    int main(){
        N=read(),Q=read(),S=read(),T=read();
        ll ans=0; 
        for(ll i=0;i<=N;i++){
            A[i]=read();if(!i) continue;
            B[i]=A[i]-A[i-1];ans+=calc(B[i]);
        }
        //cout<<sum[N+1]<<endl;
        while(Q--){
            ll l=read(),r=read(),v=read();
            ans-=calc(B[l]);B[l]+=v;ans+=calc(B[l]);
            if(r!=N) ans-=calc(B[r+1]),B[r+1]-=v,ans+=calc(B[r+1]);
            printf("%lld
    ",ans);
        }
        return 0;
    }

    总结:

    三道“思维”题$100pts$收场喜闻乐见。

    正如$Lv$神所言:“这样去考$noip$还不如回家洗洗睡”。

    的确像这种题目都不能保证$100%AC$还拿什么$noip$高分,不如去搞文化课了。

    模拟考试的时候手懒,$noip$的时候可能就一直懒下去了吧。

    后面几场模拟考试要认真打了,不然在这耗$3h$有什么意义呢。

    共勉。

  • 相关阅读:
    8-12接口测试进阶-1数据驱动
    8-5接口测试用例设计与编写-4
    用CentOS 7打造合适的科研环境
    linux版本qq的安装
    CentOS下安装福昕PDF软件
    CENTOS install summary
    centos6 install mplayer(multimedia)
    基于u盘安装centos6.0
    CentOS6.3挂载读写NTFS分区
    制作win7+ubuntu +winPE+CDlinux多系统启动U盘
  • 原文地址:https://www.cnblogs.com/YSFAC/p/9672332.html
Copyright © 2020-2023  润新知