• Codeforces Round #545题解


    A题

    做法很明显,就是隔壁连续1和连续2取min,虽然写的比较复杂

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int a[N];
    queue<int> q1,q2; 
    int main(){
        int n;
        cin>>n;
        int i;
        int ans=0;
        for(i=1;i<=n;i++){
            cin>>a[i];
        }
        int cnt1=0,cnt2=0;
        int last=0;
        int flag=0;
        for(i=2;i<=n;i++){
            if(a[i-1]!=a[i]){
                if(!flag){
                    flag=a[i-1];
                }
                if(a[i-1]==1){
                    q1.push(i-1-last);
                }
                else{
                    q2.push(i-1-last);
                }
                last=i-1;
            }
        }
        if(a[n]==2){
            q2.push(n-last);
        }
        else{
            q1.push(n-last);
        }
        while(q1.size()&&q2.size()){
            int t1=q1.front();
            int t2=q2.front();
            ans=max(ans,min(t1,t2));
            if(flag==1){
                q1.pop();
                flag=2;
            }
            else{
                flag=1;
                q2.pop();
            }
        } 
        cout<<ans*2<<endl;
        return 0;
    } 
    View Code

    B题

    这题如果直接模拟感觉讨论的情况会比较多,因此我们列方程式来做,这也会列出两个等式,我们枚举只会a的个数和每边存在会的人数的总数,这也所有变量都能够被求出来

    只有去掉非法情况并判断结果即可,没有则输出-1

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int a[N],c[N],n;
    vector<int> num[5];
    int main(){
        cin>>n;
        int i,j,k;
        int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
        string s;
        cin>>s;
        s=" "+s;
        for(i=1;i<(int)s.size();i++){
            c[i]=(s[i]=='1')?1:0;
        }
        cin>>s;
        s=" "+s; 
        for(i=1;i<(int)s.size();i++){
            a[i]=(s[i]=='1')?1:0;
        }
        for(i=1;i<=n;i++){
            if(c[i]&&!a[i]){
                cnt1++;
                num[1].push_back(i);
            }
            if(!c[i]&&a[i]){
                cnt2++;
                num[2].push_back(i);
            }
            if(c[i]&&a[i]){
                cnt3++;
                num[3].push_back(i);
            }
            if(!c[i]&&!a[i]){
                num[4].push_back(i);
                cnt4++;
            }
        }
        for(i=0;i<=cnt1+cnt3;i++){
            for(j=0;j<=i&&j<=cnt1;j++){
                int tmp=i-j;
                if(tmp<0||tmp>cnt3)
                    continue;
                int b=cnt2-2*i+cnt3+j;
                if(b<0||b>cnt2)
                    continue;
                int d1=n/2-b-i;
                int d2=n/2-cnt1-cnt2-cnt3+b+i;
                if(d1<0||d1>cnt4)
                    continue;
                if(d2<0||d2>cnt4)
                    continue;
                if(d1+d2==cnt4){
                    for(int k=0;k<j;k++){
                        cout<<num[1][k]<<" ";
                    }
                    for(int k=0;k<b;k++){
                        cout<<num[2][k]<<" ";
                    }
                    for(int k=0;k<i-j;k++){
                        cout<<num[3][k]<<" ";
                    }
                    for(int k=0;k<d1;k++){
                        cout<<num[4][k]<<" ";
                    } 
                    cout<<endl;
                    return 0;
                }
            }
        }
        cout<<-1<<endl;
        return 0;
    } 
    View Code

    C题

    这题比B题简单,重新赋值其实相当于找离散化的值,我们又注意到,只有交点对左右两边都有影响,因此取这个交点在行列中离散话较大的值,因为这个交点只能取一个值

    显然小的就要变成大的,以此类推,全部平移差值之后取行列max

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e6+10;
    int a[1010][1010];
    vector<int> row[N];
    vector<int> col[N];
    int ans[1010][1010];
    int main(){
        ios::sync_with_stdio(false);
        int n,m;
        cin>>n>>m;
        int i,j;
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                cin>>a[i][j];
                row[i].push_back(a[i][j]);
                col[j].push_back(a[i][j]);
            }
        }
        for(i=1;i<=n;i++){
            sort(row[i].begin(),row[i].end());
            row[i].erase(unique(row[i].begin(),row[i].end()),row[i].end());
        }
        for(i=1;i<=m;i++){
            sort(col[i].begin(),col[i].end());
            col[i].erase(unique(col[i].begin(),col[i].end()),col[i].end());
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                int pos1=lower_bound(row[i].begin(),row[i].end(),a[i][j])-row[i].begin()+1;
                int pos2=lower_bound(col[j].begin(),col[j].end(),a[i][j])-col[j].begin()+1;
                int mx;
                if(pos1>pos2){
                    mx=(int)col[j].size()+pos1-pos2;
                    ans[i][j]=max(mx,(int)row[i].size());
                }
                else{
                    mx=(int)row[i].size()+pos2-pos1;
                    ans[i][j]=max(mx,(int)col[j].size());
                }
            }
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                cout<<ans[i][j]<<" ";
            }
            cout<<endl;
        }
    }
    View Code

    D题

    贪心思路,因为要求出现次数最多,所以除去非法情况,我们刚开始直接生成一个t一定不劣

    那么之后我们发现,只要找到t串前后缀最大的地方,这样是最优的,因为可以用最小的代价又产生一个t串,那么这个其实就是kmp算法。

    之后就是不停循环构造直到字符不够

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e6+10;
    int ne[N];
    int main(){
        ios::sync_with_stdio(false);
        string s,t;
        cin>>s>>t;
        int i,j;
        int cnt1=0,cnt0=0;
        if(t.size()>s.size()){
            cout<<s<<endl;
            return 0;
        }
        s=" "+s;
        t=" "+t;
        string res=" ";
        for(i=1;i<(int)s.size();i++){
            if(s[i]=='1')
                cnt1++;
            else
                cnt0++;
        }
        int flag=0;
        for(i=1;i<(int)t.size();i++){
            if(t[i]=='1'){
                if(cnt1){
                    res+=t[i];
                    cnt1--;
                }
                else{
                   flag=1;
                }
            }
            else{
                if(cnt0){
                    res+=t[i];
                    cnt0--;
                }
                else{
                    flag=1;
                }
            }
        }
        if(flag){
            cout<<s.substr(1)<<endl;
            return 0;
        }
        for(i=2,j=0;i<(int)t.size();i++){
            while(j&&t[i]!=t[j+1]){
                j=ne[j];
            }
            if(t[j+1]==t[i]){
                j++;
            }
            ne[i]=j;
        }
        int pos=ne[(int)t.size()-1]+1;
        flag=0;
        while(1){
            for(i=pos;i<(int)t.size();i++){
                if(t[i]=='1'){
                    if(cnt1){
                        res+=t[i];
                        cnt1--;
                    }
                    else{
                        flag=1;
                        break;
                    }
                }
                else{
                    if(cnt0){
                        res+=t[i];
                        cnt0--;
                    }
                    else{
                        flag=1;
                        break;
                    }
                }
            }
            if(flag)
                break;
            pos=ne[(int)t.size()-1]+1;
        }
        while(cnt1--){
            res+='1';
        }
        while(cnt0--){
            res+='0';
        }
        cout<<res.substr(1);
    }
    View Code

    E题

    本题思路比较巧妙,首先要观察的一点是,每个点都能被看成d个点,表示每个天数,这是根据我们的题目发现天数很少可以看出来

    那么接下来考虑如何转移,这时候我们发现因为有环,所以不能直接跑,一般环问题我们都会转化成缩点变成dag问题,这题也不例外,只要缩完点,那么一个连通分量里能走到的点的权值肯定是已知的

    之后就是去跑最长路即可,用这种办法写很卡空间,很不幸,我没卡过去,这里会MLE在73个点,建议观看别人的代码卡空间,有空我再调一调

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=100005*50;
    int n,m,d;
    int h[N],ne[N],e[N],idx;
    int dfn[N],low[N],times;
    stack<int> q,tmp;
    ll dis[200100];
    int scnt,id[N];
    int vis[N],ins[N];
    int f[N];
    int val[N];
    int h1[N],ne1[N],e1[N],idx1;
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void add1(int a,int b){
        e1[idx1]=b,ne1[idx1]=h1[a],h1[a]=idx1++;
    }
    int get(int i,int j){
        return j*n+i;
    }
    void tarjan(int u){
        dfn[u]=low[u]=++times;
        q.push(u);
        ins[u]=1;
        int i;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(!dfn[j]){
                tarjan(j);
                low[u]=min(low[u],low[j]);
            }
            else if(ins[j]){
                low[u]=min(low[u],dfn[j]);
            }
        }
        if(dfn[u]==low[u]){
            ++scnt;
            while(1){
                int t=q.top();
                q.pop(),ins[t]=0;
                id[t]=scnt;
                int x,y;
                x=(t-1)%n+1,y=(t-1)/n;
                if(!vis[x]&&((dis[x]>>y)&1)){
                    val[scnt]++;
                    vis[x]=1;
                    tmp.push(x);
                }
                if(t==u)
                break;
            }
        }
        while(tmp.size()){
            auto t=tmp.top();
            tmp.pop();
            vis[t]=0;
        }
    }
    int dfs(int u){
        if(vis[u])return f[u];
        vis[u]=1;
        for(int i=h1[u];i!=-1;i=ne1[i]){
            int v=e1[i];
            f[u]=max(f[u],dfs(v));
        }
        return f[u]+=val[u];
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m>>d;
        int i,j;
        memset(h,-1,sizeof h);
        memset(h1,-1,sizeof h1);
        for(i=1;i<=m;i++){
            int u,v;
            cin>>u>>v;
            for(j=0;j<=d-1;j++){
                add(get(u,j),get(v,(j+1)%d));
            }
        }
        for(i=1;i<=n;i++){
            string s;
            cin>>s;
            for(j=0;j<d;j++){
                dis[i]|=1ll*(s[j]-'0')<<j;
            }
        }
        tarjan(1);
        for(i=1;i<=n*d;i++){
            if(!dfn[i])continue;
            int u=id[i];
            for(int j=h[i];j!=-1;j=ne[j]){
                int v=e[j];
                if(!dfn[v])
                    continue;
                v=id[v];
                if(u!=v){
                    add1(u,v);
                }
            }
        }
        cout<<dfs(id[1])<<endl;
    }
    View Code

    F题

    交互题,使用floyd消圈法,因为不太想写交互题,所以这题就略过了

    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    多线程
    JS实现隔行变色及鼠标滑过变色
    通用存储过程
    三级嵌套
    网页内容,图片及连接 抓取通用类(转)
    获取文件夹中的图片
    上传图片生成缩略图指定生成图片宽高度边框颜色和填充颜色
    图片上传类
    ROW_NUMBER存储过程分页
    OPENDATASOURCE 链接远程数据库
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14147146.html
Copyright © 2020-2023  润新知