AcWing 1934. 贝茜放慢脚步

577 阅读3分钟

目录:算法日记

原题链接:1934. 贝茜放慢脚步 - AcWing题库

题目描述

奶牛贝茜正在参加冬季哞林匹克运动会的越野滑雪比赛。

她以每秒 11 米的速度出发。

但是,随着时间的推移,她变得越来越疲倦,她开始放慢脚步。

每次放慢脚步,贝茜的速度都会降低:减速一次后,她以每秒 1/21/2 米的速度移动,减速两次后,则以每秒 1/31/3 米的速度移动,依此类推。

你将被告知何时何地贝茜会减速。

当减速信息格式为:

T 17

意味着,贝茜在某个时间点减速,本例表示比赛开始第 1717 秒贝茜减速。

当减速信息格式为:

D 10

意味着,贝茜在某个地点减速,本例表示在行进 1010 米处减速。

给定 NN 个减速信息,请计算贝茜滑完一千米需要多少秒。

将你的答案四舍五入到最接近的整数( 0.50.5 向上舍入为 11)。

输入格式

第一行包含整数 NN

接下来 NN 行,每行描述一个减速信息,格式为 T x 或 D x

无论哪种情况,xx 都是一个整数,保证所有减速都在贝茜滑完一千米前发生。

可能同时发生多次减速,那么这会使得贝茜的速度一下子变慢很多。

所有减速信息不一定按顺序给出。

输出格式

输出贝茜滑完一千米所需的总时间。

数据范围

1N100001≤N≤10000

输入样例

2
T 30
D 10

输出样例

2970

算法思路

如果仅考虑时间减速或地点减速,把对应序列排个序计算就可以完成。这里比较难处理的是同时存在时间减速和地点减速。单个序列好处理,因此考虑能否把时间序列和地点序列进行合并,并且需要保证排序后的序列无论是从时间还是地点看,仍是升序

因此,我们设当前所处地点为ss,当前所处时间为tt,为了保证sstt可以比较大小,引入速度vv。由于题目中速度vv11开始以1/(1+n)1/(1+n)(n为减速次数)的方式减小,为了方便处理,我们vv为速度的倒数,设a[i]表示时间序列,b[j]表示地点序列,离当前位置最近的点(sstt表示同一位置,同时更新)先减速,不妨以时间为衡量单位,则:

ta=a[i]ttb=(b[j]s)vt_a = a[i] - t\\ t_b = (b[j] - s) * v

按上述大小关系进行二路归并

AC代码

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> a, b;
int n;
char op;
int x;
int main() {
    cin>>n;
    while(n--) {
        cin>>op>>x;
        if(op == 'T') a.push_back(x);
        else b.push_back(x);
    }
    b.push_back(1000);
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    
    double s = 0;
    double t = 0;
    double v = 1;
    
    int i = 0;
    int j = 0;
    while(i < a.size() || j < b.size()) {
        if(j == b.size() || i < a.size() && a[i] - t < (b[j] - s) * v) {
            s += (a[i] - t) / v;
            t = a[i];
            i += 1;
            v += 1;
        } else {
            t += (b[j] - s) * v;
            s = b[j];
            j += 1;
            v += 1;
        }
    }
    printf("%.0lf", t);
    return 0;
}