AtCoder Beginner Contest 098 游记+题面+题解

游记

今天下午省选模拟打得我心态爆炸,晚上打打abc压压惊。

开场过了 5 5 分钟我才开始打,这让我成为了第一版(A题开局)A掉A题最慢的人了。

被wzy奶了一口AK,好像真AK了……

wzy:“abc的题目啥时候这么水了啊。”

rating change

垃圾abc,辛辛苦苦打个3rd才给我加这么点rating,以后再也不打abc了。

A - Add Sub Mul

题目大意

给出a,b,求 a+b,ab,a×b a + b , a − b , a × b 中的最大值。

思路

这……水了点吧。

B - Cut and Count

题目大意

给出一个字符串 S S ,长度100,现在你可以把字符串分成两段,求分成两段后,两段中共有字母的最大个数。

例如,aabbca这个字符串,可以分成aab,bca两个串,共有字母为a和b,个数即为2。

思路

枚举断点,暴力统计答案即可。

C - Attention

题目大意

N N 个人从西向东站成一排,每个人朝向东或西,题目给出。现在要选取一个leader,使所有人都面向他(leader的朝向随意),求需要更改朝向的人的最小个数。N3×105

思路

需要更改朝向的人数,就是leader左侧朝向左和leader右侧朝向右的人数之和,而这两个显然可以对所有点同时 O(N) O ( N ) 的统计。

D - Xor Sum 2

题目大意

给定序列 A A ,长度为N,求满足下面条件的 l,r l , r 个数:

Al+Al+1++Ar=Al xor Al+1 xor  xor Ar A l + A l + 1 + ⋯ + A r = A l   x o r   A l + 1   x o r   ⋯   x o r   A r

N2×105,Ai220 N ≤ 2 × 10 5 , A i ≤ 2 20

思路

满足条件,就是 l l r中,枚举每个二进制位,这个二进制位为 1 1 的数的个数都要小于等于1

观察到,如果 l l 增加,对应最大的r一定是单调递增的。可以用two-pointer解决。

代码

A - Add Sub Mul

#include <cstdio>
#include <algorithm>

int a,b;

int main()
{
  scanf("%d%d",&a,&b);
  printf("%d\n",std::max(std::max(a+b,a-b),a*b));
  return 0;
}

B - Cut and Count

#include <cstdio>
#include <cstring>

const int maxn=100;

char s[maxn+2];
int have[2][30],ans,n;

int main()
{
  scanf("%d%s",&n,s+1);
  for(int i=1; i<n; ++i)
    {
      memset(have,0,sizeof have);
      int cnt=0;
      for(int j=1; j<=i; ++j)
        {
          have[0][s[j]-'a'+1]=1;
        }
      for(int j=i+1; j<=n; ++j)
        {
          have[1][s[j]-'a'+1]=1;
        }
      for(int j=1; j<=26; ++j)
        {
          if(have[0][j]&&have[1][j])
            {
              ++cnt;
            }
        }
      if(cnt>ans)
        {
          ans=cnt;
        }
    }
  printf("%d\n",ans);
  return 0;
}

C - Attention

#include <cstdio>

const int maxn=300000;
const int inf=0x3f3f3f3f;

char s[maxn+10];
int n,f[maxn+10],g[maxn+10],ans;

int main()
{
  scanf("%d%s",&n,s+1);
  for(int i=2; i<=n; ++i)
    {
      f[i]=f[i-1]+(s[i-1]=='W');
    }
  for(int i=n-1; i; --i)
    {
      g[i]=g[i+1]+(s[i+1]=='E');
    }
  ans=inf;
  for(int i=1; i<=n; ++i)
    {
      if(f[i]+g[i]<ans)
        {
          ans=f[i]+g[i];
        }
    }
  printf("%d\n",ans);
  return 0;
}

D - Xor Sum 2

#include <cstdio>

const int maxn=200000;

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

int n,a[maxn+10],t[maxn+10][23],now[23];
long long ans;

inline int trans(int v,int pos)
{
  int x=1;
  while(v)
    {
      t[pos][x]=v%2;
      ++x;
      v/=2;
    }
  return 0;
}

inline int check(int pos)
{
  for(int i=1; i<=20; ++i)
    {
      if(now[i]&&t[pos][i])
        {
          return 0;
        }
    }
  return 1;
}

int main()
{
  n=read();
  for(int i=1; i<=n; ++i)
    {
      a[i]=read();
      trans(a[i],i);
    }
  int r=1;
  for(int i=1; i<=20; ++i)
    {
      now[i]=t[1][i];
    }
  for(int l=1; l<=n; ++l)
    {
      for(int i=1; i<=20; ++i)
        {
          now[i]^=t[l-1][i];
        }
      while((r<n)&&(check(r+1)))
        {
          ++r;
          for(int i=1; i<=20; ++i)
            {
              now[i]|=t[r][i];
            }
        }
      ans+=r-l+1;
    }
  printf("%lld\n",ans);
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值