Codeforces Round #581 (div. 2) 题解

算法竞赛 比赛-Codeforces
编辑文章

补的,这真是一场神仙Round。

A.BowWow and the Timetable

题意

题解

可以发现一般情况下答案只与最高位有关,但如果是刚好 $4^x$ 的话就需要看后面有没有 $1$ ,如果没有那答案要 $-1$ 。

#include<bits/stdc++.h>

using namespace std;

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

int n,ans;
char s[105];

signed main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    reverse(s+1,s+n+1);
    int cnt=0;
    for (int i=1;i<=n;i++)
    {
        if (s[i]=='1')
        {
            ans=max(ans,(i+1)>>1);
            if (n&1 && i==n && !cnt) ans--;
            cnt++;
        }
    }
    return !printf("%d",ans);
}

B.Mislove Has Lost an Array

题意

题解

贪心。最小的情况就是加到 $l$ ,剩下全为 $1$ ;最大就加到 $r$ ,剩下全为 $2^{r-1}$ 。

#include<bits/stdc++.h>

using namespace std;

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

int n,l,r;

signed main()
{
    n=read(); l=read(); r=read();
    int ans=0,cur=1;
    for (int i=1;i<=l;i++) ans+=cur,cur<<=1;
    printf("%d ",ans+n-l);
    ans=0,cur=1;
    for (int i=1;i<=r;i++) ans+=cur,cur<<=1;
    cur>>=1;
    return !printf("%d",ans+(n-r)*cur);
}

C.Anna, Svyatoslav and Maps

题意

简单的说就是固定最少的点,使得任意固定的两点之间最短路径之一是原路径。

题解

可以先用 $\text{Floyd}$ 跑出两两之间的最短路。

首先固定起点 $P_1$ 。然后从 $i=3$ 开始遍历 $P_i$ ,如果固定的最后一个点 $P_{last} \rightarrow P_i \le P_{last+1}\rightarrow P_i$ ,那么就固定 $P_{i-1}$ ,同时更新 $last=i-1$。

#include<bits/stdc++.h>

using namespace std;

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

int n,m,dis[105][105],p[1000005],ans[1000005],acnt;

signed main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        char ch[105]; scanf("%s",ch+1);
        for (int j=1;j<=n;j++) dis[i][j]=(i==j) ? 0 : (ch[j]=='1') ? 1 : 1e9;
    }
    m=read();
    for (int i=1;i<=m;i++) p[i]=read();
    for (int k=1;k<=n;k++)
    {
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
            {
                if (dis[i][k]+dis[k][j]>=dis[i][j]) continue;
                dis[i][j]=dis[i][k]+dis[k][j];
            }
        }
    }
    ans[++acnt]=p[1];
    int cnt=1; //cnt就是 Plast->Pi 的距离
    for (int i=3;i<=m;i++)
    {
        if (dis[ans[acnt]][p[i]]>cnt) cnt++;
        else ans[++acnt]=p[i-1],cnt=1;
    }
    ans[++acnt]=p[m];
    printf("%d\n",acnt);
    for (int i=1;i<=acnt;i++) printf("%d ",ans[i]);
    return 0;
}

D.Kirk and a Binary String

题意

题解

可以发现一定是把原序列中的 $1$ 变成 $0$ ,那么题目就变成了选一些 $1\rightarrow 0$ 。

当一个数是 $1$ 时,它只能连接后面的 $1$ ;变 $0$ 后就能连 $0$ 了,所以只要它后面 $0$ 的个数 $\le$ $1$ 的个数,那么就可以选它。

至于以它为终点的区间,因为它前面连续的 $1$ 也会随之被删掉,所以它们之间的不降序列个数不变。

#include<bits/stdc++.h>

using namespace std;

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

int n;
char s[100005];

signed main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    int sum=0; //0与1个数的差
    for (int i=n;i;i--)
    {
        if (s[i]=='0') sum++;
        else if (sum) sum--;
        else s[i]='0';
    }
    return !printf("%s",s+1);
}

新评论

称呼不能为空
邮箱格式不合法
网站格式不合法
内容不能为空