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

相关推荐
爱装代码的小瓶子12 小时前
【c++知识铺子】封装map和set(详细版)
android·java·c++
Aaron158812 小时前
RFSOC+VU13P在无线信道模拟中的技术应用分析
数据结构·人工智能·算法·fpga开发·硬件架构·硬件工程·射频工程
明洞日记12 小时前
【VTK手册026】高性能网格简化——vtkQuadricClustering 深度解析
c++·图像处理·vtk·图形渲染
咸鱼加辣12 小时前
“刻意强调” O(1)
数据结构·算法
南烟斋..12 小时前
Linux进程管理完全指南:创建、终止、回收与替换
linux·算法
东华万里12 小时前
第十五讲 指针 从本质吃透 C 语言指针(上)
c语言·开发语言
xiaoye-duck12 小时前
C++入门基础指南:引用全解析(从入门到精通)
c++
点我头像干啥12 小时前
机器学习算法之动量法:优化梯度下降的“惯性”策略
人工智能·神经网络·算法·机器学习
XFF不秃头13 小时前
力扣刷题笔记-下一个排列
c++·笔记·算法·leetcode
Lv117700813 小时前
Visual Studio中Array数组的常用查询方法
笔记·算法·c#·visual studio