zoukankan      html  css  js  c++  java
  • Codeforces Round #590 (Div. 3) 训练总结及A-F题解

    总结:A5mins ac,B过的慢22mins ac,接着就被c卡了一小时1小时ac,写到了d题,因为打星练了下手速,无板子17mins ac还算不错,e是个差分,f思维题。
    总结:

    1. C题想多一点,就节省了很多代码量。
    2. E题要静下心写。

    题解:
    A.
    题意:00个货物,价格不一。使所有货物价格变为一个价格,且新总价格>=原sum且要求变动最小。
    思路:-1找到平均值+1
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 2e9+5;
    const ll INF = 2e18+5;
    
    int main(){
        IO;cout.precision(10);cout<<fixed;  
        int t;cin>>t;
        while(t--){
            int n;cin>>n;
            int sum = 0;
            forn(i,n){
                int x;cin>>x;
                sum+=x;
            }
            sum--;
            sum/=n;
            sum++;
            sum;
            cout<<sum<<'
    ';
        }
        return 0;
    }
    

    B.
    题意:2e5个数,你的显示器每次只能显示k个数,按顺序来如果新来的数字在显示器上,则不更新显示器,如果超过k个数,挤掉显示器进入最早的数。
    思路:维护一个set来确定进不进,维护一个deque来确定删哪个。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 2e9+5;
    const ll INF = 2e18+5;
    
    int main(){
        IO;cout.precision(10);cout<<fixed;  
        set<int>s;
        deque<int>ans;
        int n,k;cin>>n>>k;
        forn(i,n){
            int x;cin>>x;
            if(s.find(x)!=s.end()) continue;
            if(ans.size()<k){
                s.insert(x);
                ans.push_back(x);
                continue;
            }
            int y = ans.front();ans.pop_front();
            s.erase(s.find(y));
            s.insert(x);ans.push_back(x);
        }
        cout<< ans.size() <<'
    ';
        while(!ans.empty()){
            cout<<ans.back()<<' ';
            ans.pop_back();
        }
        return 0;
    }
    

    C
    题意:如图从左上走到右下,地图大小2*n(n2e5),每个管道可以旋转。问能否走出去。在这里插入图片描述
    思路:bfs或者按顺序走就可以。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 2e9+5;
    const ll INF = 2e18+5;
    struct node{
        int x,y,p;
    };
    const int maxn = 2e5+5;
    
    bool vis[2][maxn];
    int dy[] = {0,0,1},dx[] = {1,-1,0};
    
    int main(){
        IO;cout.precision(10);cout<<fixed;  
        int t;cin>>t;
        while(t--){
            int n;cin>>n;
            string s[2];cin>>s[0]>>s[1];
            queue<node>q;
            node now = {0,0,2};
            bool ok = 0;
            q.push(now);
            while(!q.empty()){
                now = q.front();q.pop();
                int x = now.x,y = now.y,p = now.p;
                //cerr<<"@!#!@#   "<<x<<' '<<y<<'
    ';
                if(x==1&&y==n-1){
                    //cerr<<"@!@!#@!#@!   "<<s[x][y]<<' '<<p<<'
    ';
                    if(s[x][y]>='1'&&s[x][y]<='2'){
                        if(p==2) ok = 1;
                    }else{
                        if(p==0) ok = 1; 
                    }
                }
                if(s[x][y]>='1'&&s[x][y]<='2'){
                    if(p!=2) continue;
                    int nx = x+dx[2],ny = y+dy[2];
                    if(nx<0||nx>1||ny<0||ny==n)continue;
                    if(vis[nx][ny]) continue;
                    vis[nx][ny] = 1;
                    q.push({nx,ny,2});
                }else{
                    if(p!=2){
                        int nx = x+dx[2],ny = y+dy[2];
                        if(nx<0||nx>1||ny<0||ny==n)continue;
                        if(vis[nx][ny]) continue; 
                        vis[nx][ny] = 1;
                        q.push({nx,ny,2});
                    }else{
                        forn(i,2){
                            int nx = x+dx[i],ny = y+dy[i];
                            if(nx<0||nx>1||ny<0||ny==n)continue;
                            if(vis[nx][ny]) continue; 
                            vis[nx][ny] = 1;
                            q.push({nx,ny,i});
                        }
                    }
                }
            }
            if(!ok) cout<<"NO"<<'
    ';
            else cout<<"YES"<<'
    ';
            forn(i,2) forn(j,n) vis[i][j] = 0;
        }
        return 0;
    }
    

    D.
    题意:1e5的字符串,两种操作:1.修改某位置字符 2.查询区间字符不相同数。
    思路:线段树,字母表对应二进制的位数,用或操作。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 2e9+5;
    const ll INF = 2e18+5;
    const int maxn = 1e5+5;
    
    int a[maxn],n,now;
    class segment_tree{
        public:
        #define nd node[now]
        #define ndl node[now<<1]
        #define ndr node[now<<1|1]
        struct segement_node{
            int l,r,v;
        }node[maxn<<2];
        void pushup(int now){
            nd.v = ndl.v|ndr.v;
        }
        void maketree(int l,int r,int now = 1){
            nd = {l,r,0};
            if(l==r){
                nd.v = (1<<a[l]);
                return;
            } 
            maketree(l,l+r>>1,now<<1);
            maketree((l+r>>1)+1,r,now<<1|1);
            pushup(now);
        }
        void update(int pos,int v,int now = 1){
            if(nd.l==nd.r){
                nd.v = (1<<v);
                return;
            }
            if(pos<=ndl.r) update(pos,v,now<<1);
            else update(pos,v,now<<1|1);
            pushup(now);
        }
        int query(int l,int r,int now = 1){
            if(l<=nd.l&&r>=nd.r) return nd.v;
            int res = 0;
            if(l<=ndl.r) res|=query(l,r,now<<1);
            if(r>=ndr.l) res|=query(l,r,now<<1|1);
            return res;
        }
    }tree;
    
    int main(){
        IO;cout.precision(10);cout<<fixed;  
        string s;cin>>s;
        n = s.size();
        for1(i,n) a[i] = s[i-1]-'a';
        tree.maketree(1,n);
        int q;cin>>q;
        while(q--){
            int op;cin>>op;
            if(op==1){
                int pos;char c;cin>>pos>>c;
                int v = c-'a';
                tree.update(pos,v);
            }else{
                int l,r;cin>>l>>r;
                int x = tree.query(l,r),res = 0;
                forn(i,26){
                    int y = 1<<i;
                    if(x&y) res++;
                }
                cout<<res<<'
    ';
            }
        }
        return 0;
    }
    

    E
    题意:从1-n的序列,pi(n)函数会把序列中第i个值提出来放到序列第一位。然后告诉你一个pos(pi,xi)函数,会找到pi序列的第xi个值,xi是给定的数组,再告诉你一个F函数,求1-n每个f函数的值。具体函数看题目。
    思路:分类讨论,然后差分
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 2e9+5;
    const ll INF = 2e18+5;
    const int maxn = 2e5+5;
    
    int a[maxn];
    ll sum[maxn];
    
    int main(){ 
        IO;cout.precision(10);cout<<fixed;  
        int n,m;cin>>n>>m;
        for1(i,m) cin>>a[i];
        for1(i,m-1){
            int x = min(a[i],a[i+1]),y = max(a[i],a[i+1]);
            if(x==y) continue;
            sum[1]+=y-x;
            sum[x]-=y-x;
            sum[x]+=y-1;
            sum[x+1]-=y-1;
            sum[x+1]+=y-x-1;
            sum[y]-=y-x-1;
            sum[y]+=x;
            sum[y+1]-=x;
            sum[y+1]+=y-x;
        }  
        for1(i,n){
            sum[i] = sum[i]+sum[i-1];
            cout<<sum[i]<<' ';
        }
        return 0;
    }
    

    F.
    题意:
    F题意是1e6长度的字符串,你可以进行一次操作,操作可以选择一段区间反转字符串。你的目的是尽可能找到一段最长区间,使得区间内每一个字母都只出现一次。输出这个区间的最大长度。
    思路:
    问题等价于找到两个完美区间,且这两个区间任取字符不同,且总字符数最大。
    转换成这个问题之后就可以dp+二进制了。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 2e9+5;
    const ll INF = 2e18+5;
    
    int a[1<<20];
    
    int main(){
        IO;cout.precision(10);cout<<fixed;  
        string s;cin>>s;
        int n = s.size();
        forn(i,n) s[i]-='a';
        forn(i,n){
            int num = 0;
            for(int j = i;j<n;j++){
                if(num&(1<<s[j])) break;
                num|=(1<<s[j]);
                a[num] = __builtin_popcount(num);
            }
        }
        forn(j,1<<20){
            forn(i,20)if(j&(1<<i)){
                a[j] = max(a[j],a[j^(1<<i)]);
            }
        }
        int ans = 0;
        forn(i,1<<20) ans = max(ans,a[i]+a[(1<<20)-1-i]);
        cout << ans <<'
    ';
        return 0;
    }
    
  • 相关阅读:
    Javascript 获得数组中相同或不同的数组元素
    JS 获取(期号、当前日期、本周第一天、最后一天及当前月第一、最后天函数)
    Intellij IDEA2020.2.3最新激活码激活破解方法(2020.11.26)
    【jQuery 区别】.click()和$(document).on("click","指定的元素",function(){});的区别
    pytorch repeat 和 expand 函数的使用场景,区别
    python小技巧
    提高GPU利用率
    pyinstaller 打包文件(包括使用管理员模式)
    frp 开机自启动
    AUC指标深度理解
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520293.html
Copyright © 2011-2022 走看看