智算之道模拟赛B公交换乘

公交换乘

公交换乘
共 20 个测试点  每个测试点 5 分

每个测试点限时 1 秒  运行内存上限 256MB



著名旅游城市 B 市为了鼓励大家采用公共交通方式出行,推出了一种地铁换乘公交车的优惠方案:

在搭乘一次地铁后可以获得一张优惠票,有效期为 45 分钟,在有效期内可以消耗这张优惠票,免费搭乘一次票价不超过地铁票价的公交车。在有效期内指开始乘公交车的时间与开始乘地铁的时间之差小于等于 45 分钟,即

t_bus-t_subway <= 45

搭乘地铁获得的优惠票可以累积,即可以连续搭乘若干次地铁后再连续使用优惠票搭乘公交车。

搭乘公交车时,如果可以使用优惠票一定会使用优惠票;如果有多张优惠票满足条件,则优先消耗获得最早的优惠票。

现在你得到了小轩最近的公共交通出行记录,你能帮他算算他的花费吗?

输入格式
输入第一行包含一个正整数 n,代表乘车记录的数量。

接下来的 n 行,每行包含 3 个整数,相邻两数之间以一个空格分隔。第 i 行的第 1 个整数代表第 i 条记录乘坐的交通工具,0代表地铁,1 代表公交车;第 2 个整数代表第 i 条记录乘车的票价 price_i
​	
 ;第三个整数代表第 i 条记录开始乘车的时间 t_i
​	
 (距 0 时刻的分钟数)。

我们保证出行记录是按照开始乘车的时间顺序给出的,且不会有两次乘车记录出现在同一分钟。

输出格式
输出有一行,包含一个正整数,代表小轩出行的总花费。

数据范围
对于 100% 的数据,n<=1e5,t<=1e9,pricei<=1e3

【样例输入】

6
0 10 3
1 5 46
0 12 50
1 3 96
0 5 110
1 6 135
【样例输出】

36
【样例解释】

第一条记录,在第 3 分钟花费 10 元乘坐地铁。

第二条记录,在第 46 分钟乘坐公交车,可以使用第一条记录中乘坐地铁获得的优惠票,因此没有花费。

第三条记录,在第 50 分种花费 12 元乘坐地铁。

第四条记录,在第 96 分钟乘坐公交车,由于距离第三条记录中乘坐地铁已超过 45 分钟,所以优惠票已失效,花费 3 元乘坐公交车。

第五条记录,在第 110 分钟花费 5 元乘坐地铁。

第六条记录,在第 135 分钟乘坐公交车,由于此时手中只有第五条记录中乘坐地铁获得的优惠票有效,而本次公交车的票价为 6 元,高于第五条记录中地铁的票价 5 元, 所以不能使用优惠票,花费 6 元乘坐公交车。

总共花费 36 元。

【样例输入26
0 5 1
0 20 16
0 7 23
1 18 31
1 4 38
1 7 68
【样例输出232
【样例解释2】

第一条记录,在第 1 分钟花费 5 元乘坐地铁。

第二条记录,在第 16 分钟花费 20 元乘坐地铁。

第三条记录,在第 23 分钟花费 7 元乘坐地铁。

第四条记录,在第 31 分钟乘坐公交车,此时只有第二条记录中乘坐的地铁票价高于本次公交车票价,所以使用第二条记录中乘坐地铁获得的优惠票。

第五条记录,在第 38 分钟乘坐公交车,此时第一条和第三条记录中乘坐地铁获得的优惠票都可以使用,使用获得最早的优惠票,即第一条记录中乘坐地铁获得的优惠票。

第六条记录,在第 68 分钟乘坐公交车,使用第三条记录中乘坐地铁获得的优惠票。

总共花费 32 元。

刚开始打算用数组模拟双端队列,发现使用的优惠券存在跳过第一张,先用第二张的情况,于是暴力模拟了,写一个二分,从当前位置往前45分钟找起点。这样的最坏时间复杂度是 O ( 45 n l o g n ) O(45nlogn) O(45nlogn),n的范围1e5,可写。

AC代码:

/*
 * @Author: hesorchen
 * @Date: 2020-07-03 17:05:01
 * @LastEditTime: 2020-07-07 09:11:22
 * @Description: https://hesorchen.github.io/
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define INF 0x3f3f3f3f
#define mod 9973
#define pll pair
#define lowbit(abcd) (abcd & (-abcd))
#define max(a, b) ((a > b) ? (a) : (b))
#define min(a, b) ((a < b) ? (a) : (b))

#define IOS                      \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
#define FRE                              \
    {                                    \
        freopen("in.txt", "r", stdin);   \
        freopen("out.txt", "w", stdout); \
    }

inline ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
//==============================================================================

pll sub[100010];
ll ans, pos = 1, sum = 1, n;

ll find(ll time)
{
    ll l = 1, r = sum - 1, res = sum - 1;

    while (l <= r)
    {
        ll mid = l + r >> 1;
        if (sub[mid].second >= time)
        {
            res = mid;
            r = mid - 1;
        }
        else
            l = mid + 1;
    }
    return res;
}
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        ll a, b, c;
        cin >> a >> b >> c;
        if (a)
        {
            ll flag = 0;
            ll start = find(c - 45);
            for (int j = start; j < sum; j++)
                if (c - sub[j].second <= 45 && b <= sub[j].first)
                {
                    sub[j].first = -1;
                    flag = 1;
                    break;
                }
            if (flag)
                continue;
            else
                ans += b;
        }
        else
        {
            sub[sum].first = b;
            sub[sum++].second = c;
            ans += b;
        }
    }
    cout << ans << endl;
    return 0;
}
/*
3
1 10 10
0 10 30
1 10 54
*/

你可能感兴趣的:(#,其他题解)