Codeforces Round #634 (Div. 3)题解

A. 将一个数拆成两个,两个数不等,求拆分的方法数。

  奇数输出n/2,偶数输出n/2-1即可通过。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}


int main(){
    int kase=read();
    while(kase--){
        int n=read();
        if(n&1){
            cout<<n/2<<endl;
        }else{
            cout<<n/2-1<<endl;
        }
    }

    return 0;
}
View Code

B. 构造长度为n的,每个长度为a的子串里有b个不同的字母。

  先填b个不同的,再填a-b个相同的,每次补上被移走的。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

void solve(){
    int n, a, b;
    n=read(),a=read(),b=read();

    vector<int>cnt(26,0);
    string s;
    for(int i=0;i<b;++i){
        s+=('a'+i);
        ++cnt[i];
    }
    for(int i=1;i<=a-b;++i){
        s+="a";
        ++cnt[0];
    }

    for(int i=a+1;i<=n;++i){
        --cnt[s[i-a-1]-'a'];
        if(cnt[s[i-a-1]-'a']==0){
            s+=s[i-a-1];
            ++cnt[s[i-a-1]-'a'];
        }else{
            s+="a";
            ++cnt[0];
        }
    }

    cout<<s<<endl;

}

int main(){
    int cases;cases=read();
    while(cases--){
        solve();
    }

    return 0;
}
View Code

C. 给一个数组,选择一些数。分成两组,第一组要求数值全都不同,第二组要求全都相同,问组最大能多大。

  先统计每一个数值的人数和总类别数。考虑二分答案,check一下即可。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

void solve(){
    int n=read();
    vector<int> a(n+1),cnt(n+1,0);
    for(int i=1;i<=n;++i)a[i]=read();
    for(int i=1;i<=n;++i)++cnt[a[i]];

    int num=0;
    for(int i=1;i<=n;++i){
        if(cnt[i])++num;
    }

    int l=1,r=n/2;
    int ans=0;
    while(l<=r){
        int ok=0;
        for(int i=1;i<=n;++i){
            if(cnt[i]>=mid){
                if(cnt[i]==mid){
                    if(num>mid){
                        ok=1;
                        break;
                    }
                }else{
                    if(num>=mid){
                        ok=1;
                        break;
                    }
                }
            }
        }

        if(ok){
            ans=mid;
            l=mid+1;
        }else{
            r=mid-1;
        }
    }

    cout<<ans<<endl;
}

int main(){
    int cases;cases=read();
    while(cases--){
        solve();
    }

    return 0;
}
View Code

D. 给9*9的矩阵,有9个3*3的矩阵。大矩阵保证每一行都是1到9的排列,每一列都是1到9的排列。3*3的网格里,1-9的数都是一个。现在要使得每一行,每一列,每一个3*3的网格里,重复值最多两个,请给出一种构造方案。

  将2-9的其中任何一个数字改成1都可以通过。

E. 给你一个数组,每个值都不超过200。求不同的数不超过两个的回文串,这个回文串还要满足AAA...AABBB..BAAAA..AA的形式。

  对每一个数统计位置,先更新一遍答案。再枚举一下外层的数字和数字个数(2的倍数),再枚举里面的数,在外面个数变大的时候,双指针移动一下就可以了。(看错题,写了半天最长回文子序列,蠢哭.jpg)。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T& a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T& a, T b){if(b>a)a=b;}

int n;
int a[MAXN];
vector<int> pos[205];

void solve(){
    n=read();
    for(int i=1;i<=200;++i)pos[i].clear();

    for(int i=1;i<=n;++i){
        a[i]=read();
        pos[a[i]].PB(i);
    }

    int ans=0;
    for(int i=1;i<=200;++i)ans=max(ans,SZ(pos[i]));

    for(int i=1;i<=200;++i){
        if(SZ(pos[i])==0)continue;

        for(int j=1;j<=200;++j){
            if(i==j||SZ(pos[j])==0)continue;

            int l=0,r=SZ(pos[j])-1;
            for(int num=2;num<=SZ(pos[i]);num+=2){
                while(pos[j][l]<pos[i][num/2-1])++l;
                while(pos[j][r]>pos[i][SZ(pos[i])-num/2])--r;
                chmax(ans,num+r-l+1);
            }
        }
    }

    printf("%d\n",ans);
}

int main(){
    int cases;cases=read();
    while(cases--){
        solve();
    }

    return 0;
}
View Code

F. 有一些节点,每个节点有一个颜色(黑色或者白色),每一个节点有且仅有一个出度。现在可以在这些节点上放置机器人,机器人一个时刻走一步。放置的要求是:要求每一个时刻,同一个节点山不能有两个机器人。问最多能放多少个,和在放置最多机器人的情况下,黑色节点上最多能放多少个。

扫描二维码关注公众号,回复: 10800828 查看本文章

  首先有一个观察就是,这个图只能出现简单环或者基环树两种形态的连通块。那么可以发现,能放置的最大数量就是环大小之和,这个很好理解。对于第二个需求,我们显然可以把环山的一些白色节点换成黑色节点,这个可以通过在补图上去bfs实现。或者像我一样,在dfs找环的时候就把这个做完。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 1'000'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T& a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T& a, T b){if(b>a)a=b;}

vector<string> col;
vector<string> dir;

vector<vector<int>> In, vis;

vector<vector<PII>> cyc;
vector<vector<PII>> info;

int cy;
vector<PII> st;

int n, m;
int ans[2];

void dfs(int x, int y){
    int tx=x,ty=y;
    if(dir[x][y]=='U')--tx;
    else if(dir[x][y]=='D')++tx;
    else if(dir[x][y]=='L')--ty;
    else ++ty;

    if(vis[tx][ty]){
        if(info[tx][ty]==MP(-1,-1)){
            cyc.PB(vector<PII>());
            for(int i=vis[tx][ty]-1;i<SZ(st);++i){
                info[st[i].fi][st[i].sd].fi=cy;
                info[st[i].fi][st[i].sd].sd=i-vis[tx][ty]+1;
                cyc[cy].PB(MP(st[i].fi,st[i].sd));
            }

            int sz=SZ(cyc[cy]);
            for(int i=vis[tx][ty]-2;i>=0;--i){
                int d=vis[tx][ty]-2-i+1;
                d=sz-d;
                if(d<0)d=(d%sz+sz)%sz;
                info[st[i].fi][st[i].sd].fi=cy;
                info[st[i].fi][st[i].sd].sd=d;
                if(col[st[i].fi][st[i].sd]=='0'){
                    col[st[i].fi][st[i].sd]='1';
                    col[cyc[cy][d].fi][cyc[cy][d].sd]='0';
                }
            }
            ans[0]+=sz;
            ++cy;
        }else{
            int tc=info[tx][ty].fi;
            int pos=info[tx][ty].sd;
            int sz=SZ(cyc[tc]);
            for(int i=SZ(st)-1;i>=0;--i){
                int d=SZ(st)-i;
                d=pos-d;
                while(d<0)d=(d%sz+sz)%sz;
                info[st[i].fi][st[i].sd].fi=tc;
                info[st[i].fi][st[i].sd].sd=d;
                if(col[st[i].fi][st[i].sd]=='0'){
                    col[st[i].fi][st[i].sd]='1';
                    col[cyc[tc][d].fi][cyc[tc][d].sd]='0';
                }
            }
        }
    }else{
        vis[tx][ty]=vis[x][y]+1;
        st.PB(MP(tx,ty));
        dfs(tx,ty);
    }
}


void solve(){
    cin>>n;cin>>m;

    col.resize(n);
    for(int i=0;i<n;++i)cin>>col[i];

    dir.resize(n);
    for(int i=0;i<n;++i)cin>>dir[i];

    In.assign(n,vector<int>(m,0));
    vis.assign(n,vector<int>(m,0));

    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(dir[i][j]=='U')++In[i-1][j];
            if(dir[i][j]=='D')++In[i+1][j];
            if(dir[i][j]=='L')++In[i][j-1];
            if(dir[i][j]=='R')++In[i][j+1];
        }
    }

    info.resize(n);
    for(int i=0;i<n;++i){
        info[i].resize(m);
        for(int j=0;j<m;++j){
            info[i][j]=MP(-1,-1);
        }
    }

    cy=0;
    cyc.resize(0);

    ans[0]=ans[1]=0;

    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(!In[i][j]){
                st.clear();
                st.PB(MP(i,j));
                vis[i][j]=1;
                dfs(i, j);
            }
        }
    }

    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(!vis[i][j]){
                ++ans[0];
            }
            if(col[i][j]=='0'){
                ++ans[1];
            }
        }
    }

    cout<<ans[0]<<" "<<ans[1]<<endl;
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    int kase;cin>>kase;
    while(kase--){
        solve();
    }

    return 0;
}
View Code

  

猜你喜欢

转载自www.cnblogs.com/JohnRan/p/12702340.html