Educational Codeforces Round 46 (Rated for Div. 2) C. Covered Points Count (前缀和的应用)

原题地址:http://codeforces.com/contest/1000/problem/C\

题意:给出n条线段,每条线段覆盖一定长度的区间,让你输出被1条线段,2条线段,…n条线段覆盖的点的数目.

思路:前缀和预处理.使用一个计数标记num,设每一条线段的左端点是标记为1,右端点是-1,那么只需要一边维护num,以便维护结果数组ans就行了.

注意:需要对右端点进行一些特殊处理,将右端点值+1,这样我们减去的时候就会先考虑同一位置的左端点,而且这样子减法也还是没有问题

#include <bits/stdc++.h>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 4e5 + 5;
int n, m;
struct node {
    ll x, id;
    node() {}
    node(ll x, ll id): x(x), id(id) {}
} a[maxn];
bool cmp(node a, node b) {
    if(a.x == b.x) return a.id > b.id;
    else return a.x < b.x;
}
int tot;
ll ans[maxn];
int main() {
    scanf("%d", &n);
    tot = 0;
    for(int i = 1; i <= n; i++) {
        ll x, y;
        scanf("%I64d%I64d", &x, &y);
        a[tot++] = {x, 1};
        a[tot++] = {y + 1, -1};
    }
    sort(a, a + tot, cmp);
    int num = 0;
    for(int i = 0; i < tot - 1; i++) {
        num += a[i].id;
        ans[num] += a[i + 1].x - a[i].x ;
    }
    for(int i = 1; i <= n; i++) printf("%I64d ", ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81414895