AtCoder Regular Contest 197 Div2 A,B题解

前言

这场没打,是后面补的,原本是打算把C补出来再写题解的,结果一直没补出来,所以就只能先出A,B的题解,后面看还会不会补了

题解部分

A - Union of Grid Paths

给你一个字符串和一个H行W列的表格,起点为第一行第一列,如果当前字符是D就向下走一格,如果当前字符是R就向右走一格,最终走到右下角。但是当前字符有些位置是?,请你在?位置填上D或者R使得最终能走到终点,并且计算所有满足条件的路线所覆盖的格子个数,注意一定存在满足条件的路线

这道题刚开始我的思路是想找一个规律的,但是很明显这并不现实,这其实就是一个模拟。

我们要计算覆盖的路线,但是我们又肯定不能全部路线走一遍,在纸上模拟一下就能发现,对于所有能够到达终点的路线,由于D和R的数量是相等的,所以我的改动就相当于向下一格,然后再向右走那么多步,也就是说,所有路线覆盖的格子是联通的

既然如此,我们就能找到每一行最左边的覆盖位置以及最右边的覆盖位置。至于怎么找,如果我尽量填R,那么得到的肯定是每一行最右边的覆盖位置。同理,如果我尽量填D,那么得到的肯定是每一行的最左边的覆盖位置。由此我们就能算出所有路线的覆盖格子个数

代码如下:

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) x&(-x)

const int MOD=1e9+7;
const int N=1000100;

int a[N];

void solve() {
    init();

    int h,w;
    cin>>h>>w;
    string s;
    cin>>s;
    int ans=0;
    int row=1;
    int col=1;
    map<int,int>left,right;
    int hh=h-1,ww=w-1;
    int num1=0,num2=0;
    for(int i=0;i<h+w-2;i++) hh -= (s[i]=='D'),ww -= (s[i]=='R');

    for(int i=0;i<h+w-2;i++) {//尽可能向右策略
        if(s[i]=='D') {
            right[row]=col;
            row++;
        }
        else if(s[i]=='R') col++;
        else {
            if(num2 < ww) {
                num2++;
                col++;
            }
            else {
                right[row]=col;
                row++;
            }
        }
    }
    right[row]=col;
    num1=0;
    num2=0;
    row=1;
    col=1;
    left[row]=col;

    for(int i=0;i<h+w-2;i++) {//尽可能向下策略
        if(s[i]=='D') row++,left[row]=col;
        else if(s[i]=='R') col++;
        else {
            if(num1 < hh) {
                num1++;
                row++;
                left[row]=col;
            }
            else col++;
        }
    }
    for(int i=1;i<=h;i++) ans+=right[i] - left[i] + 1;
    cout<<ans<<"\n";
}

signed main() {
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);


    //cout<<prime[cnt-1]<<"\n";
    //for(int i=1;i<=cnt;i++) cout<<prime[i]<<"\n";

    int t=1;
    cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}

B - Greater Than Average

给你一个序列,要求你找到所有的子序列中,数字大于该子序列平均值的个数最大值

我们要大于平均值的个数最大值,可以捋一下以下两点:1.添加一个比当前平均值小的数,平均值变小。2.添加一个比当前平均值大的数,平均值变大

那可能有的人就觉得说,这不是显然的吗。但很多时候就是这种显然的东西衍生出很难的题。 按照加粗的条件,首先我们肯定先放一个最小的数字在里面,这个时候平均值就是这个最小的数字

然后我是不是要增加大于平均值的元素数量,那请问我是从小到大加还是从大到小加。那肯定是从大到小加。因为我添加大于平均值的元素数量的时候,平均值也会跟着变大,那么前面的值就容易变成小于平均值,所以我们要从大到小添加大于平均值的元素

那一直添加到下一个数比平均值小怎么办,这个时候就结束了吗,是不是不一定。那我们就要继续添加一个最小的未添加的元素,然后重复这个过程

所以我们直接排序,重复以上过程即可

代码如下:

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) x&(-x)

const int MOD=1e9+7;
const int N=1000100;

int a[N];

void solve() {
    init();

    int n;
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
    sort(a+1,a+n+1);
    priority_queue<int ,vector<int> > q;
    int zhi=0;
    for(int i=1;i<=n;i++) {
        if(n * a[i] > sum) q.push(a[i]);
        else zhi=i;
    }

    int num=0;
    int maxvalue=q.size();
    while(!q.empty()) {
        num++;
        sum-=q.top();
        q.pop();
        while(zhi >= 1 && (n - num) * a[zhi] > sum) q.push(a[zhi]),zhi--;
        maxvalue=max(maxvalue,(int)q.size());
    }
    cout<<maxvalue<<"\n";
}

signed main() {
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);


    //cout<<prime[cnt-1]<<"\n";
    //for(int i=1;i<=cnt;i++) cout<<prime[i]<<"\n";

    int t=1;
    cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}

看看后面能不能把C补出来吧......

相关推荐
生信碱移23 分钟前
TCGA数据库临床亚型可用!贝叶斯聚类+特征网络分析,这篇 NC 提供的方法可以快速用起来了!
人工智能·python·算法·数据挖掘·数据分析
wang__123001 小时前
力扣1812题解
算法·leetcode·职场和发展
_Power_Y1 小时前
面试算法刷题练习1(核心+acm)
算法·面试
代码AC不AC2 小时前
【C++】类和对象【下】
开发语言·c++·类和对象·学习分享·技术交流
Leo来编程2 小时前
算法-时间复杂度和空间复杂度
算法
Echo``2 小时前
2:点云处理—3D相机开发
人工智能·笔记·数码相机·算法·计算机视觉·3d·视觉检测
星夜9822 小时前
C++回顾 Day5
开发语言·c++·算法
JK0x073 小时前
代码随想录算法训练营 Day37 动态规划Ⅴ 完全背包 零钱兑换
算法·动态规划
@Zeker3 小时前
C++多态详解
开发语言·c++
小羊不会c++吗(黑客小羊)3 小时前
【c++】 我的世界
c++