Codeforces Round 898 Div4 (A~F)

 

比赛链接

 

A.可以发现,只有abc至少有一个字母在其应在的位置上就可以输出YeS,否则输出NO


void solve(){
  string s;
  cin >> s;
  int cnt = 0;
  if(s[0]=='a') cnt++;

  if(s[1]=='b') cnt++;

  if(s[2]=='c') cnt++;
  if(cnt==0){
    cout<<"NO\n";
  }else cout<<"YES\n";
}

B.乘积最大是让最小的数加一,先排序,把最小的数加一后乘起来就是答案。

#define ll long long
void solve(){
  int n;
  cin >> n;
  vector<ll>a(n);
  ll mi = 100000000;
  for(int i = 0;i<n;i++){
      cin >> a[i];
  }
  sort(a.begin(),a.end());

  ll ma = a[0] + 1;
  // int f = 0;
  for(int i = 1;i<n;i++){
      ma*=a[i];
  }
  cout<<ma<<endl;

}

C.可以把正方形看作由外到内的层级,比如(1,9)若横坐标或者纵坐标超过了5,就将其变为10-坐标+1,(6变成5 ,可以看图) (1,9)就成了(1,2)横纵坐标小的是它的层级。这样便利这个矩阵,找到所有x的层级,累加起来就是答案。

#define ll long long
void solve(){
      char c[20][20];
      int ans = 0;
      for(int i = 1;i<=10;i++){
        for(int j = 1;j<=10;j++){
            cin >> c[i][j];
            if(c[i][j]=='X'){
                int ai = i;
                int aj = j;
                if(aj>5){
                    aj = 10 - aj + 1;
                }
                if(ai>5){
                    ai = 10 - ai + 1;
                }
                ans += min(ai,aj);
            }
        }
      }
      cout<<ans<<endl;

}

D.可以使用贪心策略:一旦便利到一个B,就立刻将其及右侧的K个都变为白色。

void solve(){
      int n,k;
      cin >> n >> k;
      string s;
      cin >> s;
      int nx = -1;
      int ans = 0;
      for(int i = 0;i<n;i++){
        if(s[i]=='B'&&i>=nx){
            nx = i + k;
            ans++;
        }
      }
      cout<<ans<<endl;

}

E.可以放弃线性做法,直接二分答案(墙的长度)复杂度为 O(n*log(x)) ,在二分答案时,如果遍历到当前的数小于mid,累加mid - a[i],如果和大于 x(给的水不够填注),说明墙高了,向左,反之亦然。

#define ll long long
void solve(){
      ll n,x;
      cin >> n >> x;
      vector<ll>a(n+1);
      for(int i = 1;i<=n;i++){
            cin >> a[i];
      }
      ll l = 1,r = 100000000000;
      while(l<=r){
        ll mid = (l+r)>>1;
        ll sum = 0;
        for(int i = 1;i<=n;i++){
            sum += max(1ll*0,mid - a[i]);
        }
        if(sum > x){
            r = mid - 1;
        }else l = mid  + 1;
      }
      cout<<r<<endl;

}

F.我的做法是先将所有合法的段全部存储,然后利用前缀和二分答案,二分时便利所有段。复杂度是 O(k*log(n))  (k为合法段的数量) 

#define ll long long
void solve(){
      int n,k;
      cin >> n >> k;
      vector<int>a(n+1);
      vector<int>h(n+1);
      vector<ll>s(n+1);//存储前缀和
      
      for(int i = 1;i<=n;i++){
            cin >> a[i];
            s[i] = s[i-1] + a[i];
      }
      for(int i = 1;i<=n;i++){
            cin >> h[i];
      }
      int cnt = 0;
      vector<pair<int,int>> res;//存储合法段
      int f = 0;
      for(int i = 0;i<n;i++){
        if(h[i]%h[i+1]==0){
                cnt++;
        }else{
                // cout<<i<<' ';
                res.push_back({i+1-cnt,i});
                cnt = 1;
            }
      }
      res.push_back({n-cnt+1,n});
      int l = 0,r = n;

      //二分答案
      while(l<=r){
        int mid = (l+r)>>1;
        int f = 0;
           for(auto q:res){
                int x = q.first,y = q.second;
                if(mid>(y-x+1)){
                    continue;
                }
                ll sum = 0;
                for(int i = x,j = x+mid;j<=y;i++,j++){
                    if(s[j] - s[i-1]<=k){
                        f = 1;
                    }
                }
            }
            if(f){
                l = mid + 1;
            }  else r = mid - 1;
      }
      cout<<l<<'\n';
     

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值