zoukankan      html  css  js  c++  java
  • 2020 CSP-J复赛题解

    身为一名高中生,却还是不知廉耻地做了一遍普及组的题目,体验一把AK的感觉


    T1 优秀的拆分

    传送门

    T1还是一如既往的水。

    根据题意,奇数直接-1,偶数就从一个很大的2的幂开始枚举,n比这个数大就输出这个数并且n减去这个数,然后这个数/2。

    #include<iostream>
    using namespace std;
    int n;
    int main() {
        cin>>n;
        if(n&1){
            cout<<-1;
            return 0;
        }
        for(int i=(1<<30);i>0;i/=2){
            if(n>=i){
                cout<<i<<" ";
                n-=i;
            }
        }
        return 0;
    }
    优秀的拆分

    T2 直播获奖

    传送门

    今年的T2还是比较难的,用到了两个大根堆。

    建议先看看这两个题:

    洛谷 P1168 中位数

    洛谷 P1801 黑匣子

    再看这个题就很板子了。

    计算出小根堆的大小,然后不断push和pop操作即可。

    #include<iostream>
    #include<queue>
    using namespace std;
    priority_queue<int> q1;
    priority_queue<int,vector<int>,greater<int> > q2;
    int n,w,a[100005];
    int main(){
        cin>>n>>w;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++){
            int k=max(1,i*w/100);
            if(q2.empty()||q2.top()<=a[i]) q2.push(a[i]);
            else q1.push(a[i]);
            while(!q2.empty()&&q2.size()>k){
                q1.push(q2.top());
                q2.pop();
            }
            while(q2.empty()||q2.size()<k){
                q2.push(q1.top());
                q1.pop();
            }
            cout<<q2.top()<<" ";
        }
        return 0;
    }
    直播获奖

    T3 表达式

    传送门

    这个题就比较毒瘤。不但码量大,而且规律比较不明显。

    后缀表达式用栈处理,不会的可以看看这个板子:P1449 后缀表达式

    这个题先O(n)求出没取反前的答案,然后对于这q个询问,很显然不能每个询问改变一下再求,所以我们只能去寻找规律,做到O(1)出答案。

    我们不难发现,对于每一个操作符,不管操作数是什么,答案最终只可能是0或者1,我们就可以记录下每一个操作符所对应的结果,并且记录这个结果是有哪两个操作数得来的,和这个结果所影响的下一步操作的编号是什么。

    存在一个结构体里,即下标表示编号,id表示操作符类型,to表示影响的下一个操作的编号,value表示这一步的值,x1、x2表示两个操作数(!运算只用到x1)。

    然后对于每一次修改,类似记忆化搜索,递归判断对答案有没有影响,把判断出来的用vis数组标记一下,即记下变换之后对下一个操作的答案没有影响。

    因为我太菜了,所以一开始的string用了非常笨的方法处理。

    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<stack>
    #include<cstring> 
    #include<cstdio>
    using namespace std;
    const int maxn=1000005;
    struct node{
        int id;
        int to;
        int value;
        int x1,x2;
    }c[maxn*2];
    int a[maxn],n,q;
    stack<int> s;
    string ss;
    int cnt=1000000;
    int vis[maxn*2],ans;
    int sss(string ss){
        int n=0;
        for(int i=1;i<ss.length();i++) n+=(pow(10,ss.length()-i-1)*(ss[i]-'0'));
        return n;
    }
    int ssss(string ss){
        int n=0;
        for(int i=0;i<ss.length();i++) n+=(pow(10,ss.length()-i-1)*(ss[i]-'0'));
        return n;
    }
    int dfs(int num){
        if(c[num].id==0) return c[num].value=a[num];
        if(c[num].id==1){
            int x=dfs(c[num].x1),y=dfs(c[num].x2);
            if(x==1&&y==1) return c[num].value=1;
            else return c[num].value=0;
        }
        if(c[num].id==2){
            int x=dfs(c[num].x1),y=dfs(c[num].x2);
            if(x==0&&y==0) return c[num].value=0;
            else return c[num].value=1;
        }
        if(c[num].id==3){
            int x=dfs(c[num].x1);
            if(x==0) return c[num].value=1;
            else return c[num].value=0;
        }
    }
    bool query(int num){
        if(vis[num]==1) return 1;
        if(vis[num]==2) return 0;
        int too=c[num].to;
        int x=c[too].x1,y=c[too].x2;
        if(x==num) x=y;
        if(c[num].value==0){
            if(c[too].id==1&&c[x].value==1){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
            if(c[too].id==1&&c[x].value!=1) return vis[num]=1;
            if(c[too].id==2&&c[too].value==0){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
            if(c[too].id==2&&c[too].value==1) return vis[num]=1;
            if(c[too].id==3){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
        }
        if(c[num].value==1){
            if(c[too].id==1&&c[x].value==1){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
            if(c[too].id==1&&c[x].value!=1) return vis[num]=1;
            if(c[too].id==2&&c[x].value==0){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
            if(c[too].id==2&&c[x].value!=0) return vis[num]=1;
            if(c[too].id==3){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
        }
        if(c[num].value>1){
            if(c[too].id==1) return vis[num]=1;
            if(c[too].id==2&&c[x].value==0){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
            if(c[too].id==2&&c[x].value!=0) return vis[num]=1;
            if(c[too].id==3){
                query(too)?vis[num]=1:vis[num]=2;
                return vis[num]==1?1:0;
            }
        }
    }
    int main(){
        while(1){
            cin>>ss;
            if(ss[0]=='x') s.push(sss(ss));
            else{
                if('0'<=ss[0]&&ss[0]<='9'){
                    n=ssss(ss);
                    break;
                }
            else{
                if(ss[0]=='&'){
                    c[++cnt].id=1;
                    c[s.top()].to=cnt;
                    c[cnt].x1=s.top();
                    s.pop();
                    c[s.top()].to=cnt;
                    c[cnt].x2=s.top();
                    s.pop();
                    s.push(cnt);
                }else{
                    if(ss[0]=='|'){
                        c[++cnt].id=2;
                        c[s.top()].to=cnt;
                        c[cnt].x1=s.top();
                        s.pop();
                        c[s.top()].to=cnt;
                        c[cnt].x2=s.top();
                        s.pop();
                        s.push(cnt);
                    }else{
                        if(ss[0]=='!'){
                            c[++cnt].id=3;
                            c[s.top()].to=cnt;
                            c[cnt].x1=s.top();
                            s.pop();
                            s.push(cnt);
                        }
                    }
                }
            }
            }
        }
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        ans=dfs(cnt);
        if(n==1&&cnt==1000000){
            cout<<a[1];
            return 0;
        }
        cin>>q;
        vis[cnt]=2;
        for(int i=1;i<=q;i++){
            int qu;
            scanf("%d",&qu);
            if(query(qu)) printf("%d
    ",ans);
            else printf("%d
    ",!ans);
        }
        return 0;
    }
    表达式

    T4 方格取数

    传送门

    这个题就是一个比较偏板子的dp。

    用dp[i][j][0/1/2]分别表示 到第i行 第j列这个点 ,这一列从上往下/从下往上/没有约束 的最大值。

    Q:为什么没有后效性呢?

    A:因为不能往左走,所以可以一列一列处理,所以先枚举列。

    然后就是一顿转移即可。

    注意103*103*104=1010,会爆int!要用long long!

    我TM提高组因为没开long longT2炸了,现在又忘了……

    十年oi一场空,不开long long见祖宗。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn=1005;
    int n,m,a[maxn][maxn];
    long long dp[maxn][maxn][3];
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            dp[i][1][2]=dp[i-1][1][2]+a[i][1];
        }
        for(int j=2;j<=m;j++){
            dp[1][j][0]=dp[1][j-1][2]+a[1][j];
            for(int i=2;i<=n;i++){
                dp[i][j][0]=max(dp[i][j-1][2],dp[i-1][j][0])+a[i][j];
            }
            dp[n][j][1]=dp[n][j-1][2]+a[n][j];
            for(int i=n-1;i>=1;i--){
                dp[i][j][1]=max(dp[i][j-1][2],dp[i+1][j][1])+a[i][j];
            }
            for(int i=1;i<=n;i++){
                dp[i][j][2]=max(dp[i][j][0],dp[i][j][1]);
            }
        }
        cout<<dp[n][m][2];
        return 0;
    } 
    方格取数

    //期中考试炸了呜呜呜

  • 相关阅读:
    Fiddler 只看指定URL请求
    WTM框之—调整默认的删除方法
    WTM框之—调整grid的每页显示行数
    WTM框之—数据列表上添加按钮的学习记录
    Armbian欢迎信息系统状态脚本
    Shell中的${xxx%% *}字符串分割方法
    强制SSH使用密钥认证禁止密码登录
    Linux开机自动挂载外接存储
    mysql实现name姓名多个相同的数据只取一条
    git 常用命令备忘录
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14013642.html
Copyright © 2011-2022 走看看