• noip2013 提高组


    T1 转圈游戏 题目传送门

    果不其然 第一题还是模拟题 一波快速幂解决问题

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,k,x;
    int qmod(int a,int b,int c){
        int ans=1;
        while(b){
            if(b&1) ans=ans*a%c;
            b=b/2;
            a=a*a%c;
        }
        return ans;
    }
    int main()
    {
        n=read(); m=read(); k=read(); x=read(); 
        int v=qmod(10,k,n);
        printf("%d
    ",(v*m+x)%n);
        return 0;
    }
    View Code

    T2 火柴排队 题目传送门

     这是道树状数组求逆序数对的题目 当然还要加一波离散化就好了 不过这题的离散化很玄学哇 2333

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int M=100007,mod=99999997;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    struct node{int w,pos;}a[M],b[M];
    bool cmp(node a,node b){return a.w<b.w;}
    int c[M],sum[M],n;
    LL ans;
    int lowbit(int x){return x&-x;}
    void insert(int x){
        while(x<=n){
            sum[x]++;
            x+=lowbit(x);
        }
    }
    int push_sum(int x){
        int ans=0;
        while(x){ans+=sum[x]; x-=lowbit(x);}
        return ans;
    }
    int main()
    {
        n=read(); 
        for(int i=1;i<=n;i++) a[i].w=read(),a[i].pos=i;
        for(int i=1;i<=n;i++) b[i].w=read(),b[i].pos=i;
        sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp);
        for(int i=1;i<=n;i++) c[a[i].pos]=b[i].pos;
        for(int i=1;i<=n;i++){
            insert(c[i]);
            ans=(ans+i-push_sum(c[i]))%mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    T3 货车运输 题目传送门

    几乎是裸的lca吧 用lca维护一波最近公共祖先和路径最小值就好了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int M=150007; 
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int w[M],n,f[M][2]; 
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1;
        for(int i=1;i<=n;i++)
            for(int j=i-1;j;j--){
                if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1);
                if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1);
                if(f[i][0]!=1&&f[i][1]!=1) break;
            }
        printf("%d
    ",max(f[n][0],f[n][1]));
        return 0;
    }
    View Code

    T4 积木大赛  题目传送门

    这道题就是我们只考虑相邻两列h1 h2 容易证明他的无后效性

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int M=150007; 
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int w[M],n,f[M][2]; 
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1;
        for(int i=1;i<=n;i++)
            for(int j=i-1;j;j--){
                if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1);
                if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1);
                if(f[i][0]!=1&&f[i][1]!=1) break;
            }
        printf("%d
    ",max(f[n][0],f[n][1]));
        return 0;
    }
    View Code

    当然其实正解我也写了一波 比dp快很多呀 2333

    至于为什么是拐点 

    这道题就是求一个 大小大小大小或者 小大小大小大 的序列 其中大小是相对于相邻两个数而言

    我们可以分情况考虑答案

    1. 前一个数是 ‘大’ (定义为last)那么我们下一个数一定要比他小 这时我们考虑当前数 (定义为now)

    如果now<last 很明显符合 那么答案++

    如果last>=now 那么前面小于last的以及后面能<last的同样能符合now 那么我们完全可以用now代替last

    2 前一个数是 ‘下' 同1

    所以这个问题就转换成了求拐点数 拐点数+1就是答案了 2333

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int M=100007;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,v[M];
    int f,last,ans;
    void solve(){
        int sum=1;
        for(int i=2;i<=n;i++){
            if(f==1&&v[i]<last)  f=-1,sum++;
            if(f==-1&&v[i]>last) f=1,sum++;
            last=v[i];
        }
        ans=max(ans,sum);
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) v[i]=read();
        last=v[1]; f=1; solve();
        last=v[1]; f=-1; solve();
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    T5 花匠 题目传送门

    正解似乎是算拐点+1 数据随机dp水过
    0表示他是作为比较小的那个点 1则相反
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int M=150007; 
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int w[M],n,f[M][2]; 
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1;
        for(int i=1;i<=n;i++)
            for(int j=i-1;j;j--){
                if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1);
                if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1);
                if(f[i][0]!=1&&f[i][1]!=1) break;
            }
        printf("%d
    ",max(f[n][0],f[n][1]));
        return 0;
    }
    View Code

    T6 华容道 题目传送门

     这道题黄学长都弃坑了 我纠结什么呢 以后补吧 hzwer

     
  • 相关阅读:
    20162304 2017-2018-1 《程序设计与数据结构》第十周学习总结
    20162304 2017-2018-1 《程序设计与数据结构》第九周学习总结
    20162304 2017-2018-1 《程序设计与数据结构》第八周学习总结
    20162302 2017-2018-1《程序设计与数据结构》课程总结
    20162302 实验五《数据结构综合应用》实验报告
    20162302 实验四《图的实现与应用》实验报告
    20162302 《程序设计与数据结构》第十一周学习总结
    20162302 《程序设计与数据结构》第十周学习总结
    20162302 实验三《查找与排序》实验报告
    20162302 《程序设计与数据结构》第九周学习总结
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7173157.html
Copyright © 2020-2023  润新知