CodeForces - 1000C Covered Points Count(思维+暴力)

本文提供了一种解决CodeForces-1000C问题的方法,通过记录线段的起点和终点并进行排序,计算出被线段覆盖不同次数的点的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CodeForces - 1000C Covered Points Count(思维+暴力)

题目链接
题目大意:
n个线段,问被这n个线段覆盖k次(k∈[1..n])的点的个数。
题目分析:想了好久啊,感觉很熟悉的题目,就是想不出做法…
把每个线段的起点终点分别存起来,起点标记为1,终点标记为-1,然后按照起点终点的位置排序。说不清,放个图吧。
比如
3
0 3
1 3
3 8
这组样例,排完序之后的顺序就是图中绿色的编号。
这里写图片描述
我们发现,1点的标记是1,二点的标记也是1,证明他们都是起点,一开始我们设一个计数变量,我们发现点被覆盖的次数就是计数变量原来的值加上当前点的标记,这就是为什么要给起点终点标记为1,-1了。然后到达一个起点或终点的时候,只需要后边的点的编号减去前边的点编号就是我们要的被覆盖的点的个数了。
但是有个地方就变得很难处理了,我们发现345这三个点重合了,按照原来的方式求的就不对了。怎么办呢。
只要把终点往后移一个就ok了。
这里写图片描述

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 2e5 + 100;

struct node {
   ll l;
   int is;
   bool operator <(node &a) const  {
      if(l != a.l) return l < a.l;
      return is > a.is;
   }
};

vector<node> data;
ll ans[maxn];

int main()
{
    int n;
    scanf("%d", &n);
    ll s, e;
    for(int i = 0; i < n; i++) {
        scanf("%lld %lld", &s, &e);
        data.push_back((node) {s, 1});
        data.push_back((node) {e + 1, -1});
    }

    sort(data.begin(), data.end());

    int len = data.size();
    int cnt = 1;
    for(int i = 1; i < len; i++) {
        ans[cnt] += data[i].l - data[i - 1].l;
        cnt += data[i].is;
    }

    for(int i = 1; i <= n; i++) {
         printf("%lld%c", ans[i], i == n ? '\n' : ' ');
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值