zoukankan      html  css  js  c++  java
  • 校内集训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$有什么意义呢。

    共勉。

  • 相关阅读:
    【JAVA笔记——道】JAVA对象销毁
    【JAVA笔记——道】并发编程CAS算法
    httpClientUtil的get请求
    python基础 day11 下 ORM介绍 sqlalchemy安装 sqlalchemy基本使用 多外键关联 多对多关系 表结构设计作业
    python基础 day11 上 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 事务 索引 python 操作mysql ORM sqlachemy学习
    Python基础 Day10 Gevent协程 SelectPollEpoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 RedisMemcached缓存 Paramiko SSH Twsited网络框架
    python基础 day9 进程、与线程区别 python GIL全局解释器锁 线程 进程
    python基础 day8 Socket语法及相关 SocketServer实现多并发
    python基础 day7 面向对象高级语法部分 异常处理 异常处理 Socket开发基础
    python基础 day6 面向对象的特性:封装、继承、多态 类、方法、
  • 原文地址:https://www.cnblogs.com/YSFAC/p/9672332.html
Copyright © 2011-2022 走看看