题意
给n段区间的左右端点,问出现k次的点有几个,其中k = [1, n].
思路
就是一个差分嘛~
但是因为区间范围过大,所以不可能暴力整个范围,所以我们如何来统计次数呢?
对于区间端点,左端1,右断-1,按照端点升序排序。
定义now为当前点的个数,初始化当然是1,遍历[1, cnt),次数为now的点的个数自然就是info[i].pos - info[i - 1].pos
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
inline ll read()
{
ll x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
const int maxN = 200005;
struct node{
ll pos, d;
node() {}
node(ll a, ll b): pos(a), d(b) {}
friend bool operator < (node n1, node n2) { return n1.pos < n2.pos; }
}info[maxN << 1];
ll n;
ll ans[maxN];
int main()
{
int cnt = 0;
n = read();
for(int i = 0; i < n; ++ i )
{
ll l = read(), r = read();
info[cnt ++ ] = node(l, 1);
info[cnt ++ ] = node(r + 1, -1);
}
sort(info, info + cnt);
ll now = 1;
for(int i = 1; i < cnt; ++ i )
{
ans[now] += (info[i].pos - info[i - 1].pos);
now += info[i].d;
}
for(int i = 1; i <= n; ++ i )
printf("%lld%c", ans[i], " \n"[i == n]);
return 0;
}
说起来,其实不是没有接触过差分。很早那会,有人给我讲他比赛热身赛的一道题,就是差分。比这道题简单点,因为数据范围没有那么大。直接暴力就好了。
当时让我自己想,还想了很久,未果。后来他讲了,回去记了笔记,但是没有告诉我叫差分,(可能他自己也不知道(手动滑稽)后边直接忘了qaq
后来接触差分就是树状数组区间更新
但始终没有很懂吧(实话讲不是很会用树状数组,虽然短,但还是喜欢线段树
补补补补补!
冲!