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;
    }
    
  • 相关阅读:
    TCP源码—连接建立
    TCP系列02—连接管理—1、三次握手与四次挥手
    TCP系列01—概述及协议头格式
    ubuntu软件管理apt与dpkg
    318. Maximum Product of Word Lengths
    317. Shortest Distance from All Buildings
    316. Remove Duplicate Letters
    315. Count of Smaller Numbers After Self
    314. Binary Tree Vertical Order Traversal
    313. Super Ugly Number
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520293.html
Copyright © 2011-2022 走看看