Codeforces Round #721 (Div. 2)题解

比赛链接

wa得老惨了qwq,本来还以为只能一题,太惨了太惨了

A. And Then There Were K

给你一个n,求最大的k使得:
n&(n-1)&(n-2)&(n-3)&…(k)=0
思路:求n二进制最高位对应的数-1

int n;
void solve()
{
    sd(n);
    int nn=n,val=1;
    while(nn)
    {
        val<<=1;
        nn>>=1;
    }
    val>>=1;
    pd(val-1);
}

B1. Palindrome Game (easy version)

给你一个01回文串
想要将这个字符串变为全1
两个操作:
1、将其中一个0变为1,花费1
2、当该字符串不是回文串且上一个操作不是2则可将该字符串反转,花费0
ALICE先手
最后花费最少的人获胜
思路:因为当前是回文,所以ALICE第一次必花费
cnt代表0的个数,当cnt是奇数代表中间是0
cnt为1时只能只有ALICE操作
当cnt为2时的操作为(1)ALICE花费1(2)BOB反转(3)ALICE花费1
当cnt为偶数且cnt>2时,BOB每次选择ALICE对应的位置的0变为1,直到cnt为2
当cnt为奇数时,ALICE选择中间的0变为1,然后风水轮流转,cnt变为偶数,自行代入上面的情况hhh
当cnt=1时花费为1:0
当cnt为奇数时花费差1
当cnt为偶数时花费差2

int n;
char s[maxn];
void solve()
{
    sd(n);
    sc(s+1);
    int cnt=0;
    rep(i,1,n)if(s[i]=='0')cnt++;
    if(cnt==1)puts("BOB");
    else if(cnt&1)puts("ALICE");
    else puts("BOB");
}

B2. Palindrome Game (hard version)

题意同上,只是原来的串不一定是回文串
cnt为该位置为0且对应位置为0的个数
cnt1为该位置为0且对应位置为1的个数
当cnt为0时,按上一题解法
因为当cnt1>=3时,ALICE先每次都选择反转,BOB只能选择cnt1对应位置的0变为1,直到变为回文串,这时比分已经是0:cnt1了,BOB不可能反败为胜
当cnt1=2时,如果cnt为奇数,等到变为回文串时,ALICE是先手,具体同上一题;如果cnt为偶数,那么ALICE在第二次操作时选择将另一个cnt1的0变为1,然后变成的情况可参考上一题
当cnt1=1时,如果cnt为奇数,同上;否则ALICE第一步直接选择将这个0变为1,然后就变成的情况可参考上一题

int n,cnt,cnt1;
char s[maxn];
void solve()
{
    sd(n);
    sc(s+1);
    cnt=cnt1=0;
    rep(i,1,n)
    {
        if(s[i]=='1')continue;
        if(s[i]==s[n-i+1])cnt++;
        else cnt1++;
    }
    if(cnt1>=2||!cnt)
    {
        puts("ALICE");
        return;
    }
    if(cnt1==1)
    {
        if(cnt==1)puts("DRAW");
        else puts("ALICE");
        return;
    }
    if(cnt==1)puts("BOB");
    else if(cnt&1)puts("ALICE");
    else puts("BOB");
}

C. Sequence Pair Weight

给一个长度为n的数组,区间[l,r]的值为在这区间内,ai=aj的对数
让你求对于所有的子区间的值和。
害,这题有点难讲啊,毕竟我也是混过去的,暂时先只放代码吧

int n,a[maxn];
int l[maxn],pre[maxn],cnt[maxn];
ll ans,sum[maxn];
void solve()
{
    sd(n);ans=0;
    rep(i,1,n)sd(a[i]),l[i]=a[i];
    sort(l+1,l+1+n);
    int m=unique(l+1,l+1+n)-l-1;
    rep(i,1,m)pre[i]=0,sum[i]=0;
    ll sum1=0;
    rep(i,1,n)
    {
        int k=lower_bound(l+1,l+1+m,a[i])-l;
        ans+=sum1;
        sum[k]+=pre[k];
        ans+=sum[k];
        pre[k]=i;
        sum1+=sum[k];
    }
    plld(ans);    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值