AtCoder Beginner Contest 221 D - Online games

题目描述

在这里插入图片描述

Sample Input

3
1 2
2 3
3 1

Sample Output

Copy
2 2 0

题目大意

先输入数字N,代表有N个注册者,然后接下来有N行,每一行有两个数字 A i , B i A_i,B_i Ai,Bi A i A_i Ai代表第 i i i个使用者的第一次登录的时间, B i B_i Bi代表第 i i i个使用者连续登录的天数。输出有N个数字,第k个数字代表第k天有多少个使用者登录。
其实也就是给定n条线段, [ l i , r i ] [l_i,r_i] [li,ri]。对于每个k值,输出每个k值被多少条线段覆盖。

实现思路

假如说我们现在平面上有n条线段,然后我们有一个标记竖线record从左到右扫描

  • 每次遇到线段的左端点,record+1
  • 每次遇到线段的右端点,record-1
  • record的值就是当前k位置的结果了

但是有一种特殊的情况,假如说以最左的点为左端点的线段有多条,那么我们上面的做法就会导致结果错误,大家可以在纸上模拟一下。所以我们需要特判

  • 当多个相同的左端点是最左边的点时,我们要更新一下答案
  • 不是最左边的点,就不需要更新答案。

完整代码

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
    ll n;
    cin >> n;
    vector<pair<ll, ll>> vt;
    ll a, b;
    for (int i = 0; i < n; i++)
    {
        cin >> a >> b;
        vt.push_back(make_pair(a, 1));
        vt.push_back(make_pair(a + b, -1));
    }
    int now = 0;
    int p = 0;
    int ans[n + 1];
    memset(ans, 0, sizeof(ans));
    sort(vt.begin(), vt.end());
    int len = vt.size();
    for (int i = 0; i < len; i++)
    {
        if (i > 0 && vt[i].first != vt[i - 1].first)
            ans[now] += vt[i].first - p;
        p = vt[i].first;
        now += vt[i].second;
    }
    for (int i = 1; i <= n; i++)
    {
        cout << ans[i] << " ";
    }
    cout << endl;
}

题目链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值