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补出来吧......

相关推荐
tangguofeng28 分钟前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法
会员果汁1 小时前
函数调用和变长参数
c语言
xailorliu2 小时前
SLIC_超像素算法
c++·opencv·目标检测·机器学习·计算机视觉
苏打豆2 小时前
CRISP源码阅读——基于ROS2力矩反馈控制器与速度加速度零空间
c++·线性代数·算法·矩阵·机器人
蛋蛋的就会顺顺的2 小时前
hot100——矩阵
java·数据结构·算法·leetcode·力扣
老歌老听老掉牙2 小时前
麻花钻切屑形态演变的力学机制与临界条件分析
python·算法·钻头
小小龙学IT3 小时前
snap7 开源西门子 S7 通信协议库深度解析
c++·开源
zhangfeng11333 小时前
国产GPU/AI算力芯片现状(修订完整版 · 截至2026年9月
人工智能·算法·ai编程·npu
学代码的CJY3 小时前
从代码出发理解时间复杂度与空间复杂度
数据结构·算法
小溪学编程4 小时前
从 C++ 的规范变迁看语言发展
jvm·c++·面试