The 2021 CCPC Guilin Onsite 补题+总结

本文最后更新于:5 个月前

  • A. Hero Named Magnus

    题意:签到输出2n-1;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define f(a,b,c) for(ll a=b;a<c;a++)
    void solve(){
    ll x;
    cin>>x;
    cout<<x*2-1;
    }
    int main(void){
    ios::sync_with_stdio;
    cin.tie(0);
    cout.tie(0);
    ll t=1;
    cin>>t;
    while(t--){
    solve();
    if(t)cout<<'\n';
    }
    }

  • I. PTSD

    题意:规律签到;

    代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define f(a,b,c) for(ll a=b;a<c;a++)
    void solve(){
    ll n;
    string s;
    cin>>n>>s;
    ll ans=0;
    int len=1;
    for(int i=n-2;i>=0;--i){
    len++;
    if(s[i]=='0')continue;
    if(len>=2){
    ans+=i+1;
    // cout<<"ans:"<<ans<<"\n";
    len-=2;
    }

    }
    cout<<ans;

    }
    int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll t=1;
    cin>>t;
    while(t--){
    solve();
    if(t)cout<<'\n';
    }
    }
  • G. Occupy the Cities

    题意:给出一串01字符串,其中每个1每次操作可以向左一位或向右一位将临近的0变为1,问最少多少次操作能将字符串变为全一。

    解题过程:一开始想的找规律,看到题意时我就有了一个想法:首先计算最外层两一间最大的两一位置差maxv,例如 001000100100 -> maxv=3,这时只要操作满足了这个最大差,那么该区间内的其他零也都能覆盖,处理完双一内圈后再处理外围零。但是最后发现要加不少特判遂作罢。然后y同学和w同学直接想到和题解一样的方法,但是找不到处理第一步的方法。赛后看了别人都用的二分答案才恍然大悟,记录一下我对此种解法的理解:直接对答案做二分,拿答案ANS去遍历字符串看是否符合题目要求,也就是每个0的最近左1或右1距离不超过ANS,此时就可以保证该零在该种操作数下可以被覆盖,如果该ANS完全符合,再次缩小ANS判断。

    代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define u(a,b,c) for(int a=b;a<c;a++)
    #define d(a,b,c) for(int a=b-1;a>=c;a--)
    const int N=1e6+10;
    ll n;
    string s;
    vector<ll> lo(N),ro(N);//lo记录每个0左边1的位置,ro记录每个0右边1的位置
    bool ck(ll p){//判断操作数p是否符合
    vector<ll>f(n,0);//f记录1s'f
    u(i,0,n){
    if(s[i]=='1')continue;
    if(p>=min(i-lo[i],ro[i]-i)+1)continue;
    if(lo[i]>=0&&lo[i]<n&&!f[lo[i]]&&p>=i-lo[i]){
    f[lo[i]]=1;
    continue;
    }
    if(ro[i]>=0&&ro[i]<n&&!f[ro[i]]&&p>=ro[i]-i){
    f[ro[i]]=1;
    continue;
    }
    return 0;
    }
    return 1;
    }
    void solve(){
    cin>>n>>s;
    ll l=0,r=n-1;
    ll x=-1e9;
    u(i,0,n){
    lo[i]=x;
    if(s[i]=='1')x=i;
    }
    x=1e9;
    d(i,n,0){
    ro[i]=x;
    if(s[i]=='1')x=i;
    }
    while(l<r){
    ll mid=l+r>>1;
    if(ck(mid)){
    r=mid;
    }else{
    l=mid+1;
    }
    }
    cout<<l;
    }
    int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
    solve();
    if(t)cout<<'\n';
    }
    }

The 2021 CCPC Guilin Onsite 补题+总结
https://zeitspeed.github.io/2023/10/18/VPguilin2021/
作者
yxisme
发布于
2023年10月18日
许可协议