AT2300 [ARC068C] Snuke Line
https://www.luogu.com.cn/problem/AT2300
重新想的时候又没有想出来
首先有一个显然的性质,如果一个区间的长度\(len\ge d\),那么这个区间的一定能被\(d\)买到
先把区间按照长度排序,比当前\(d\)大的直接加入答案
否则把\([l_i,r_i]\)插入树状数组中,然后暴力枚举\(kd\),因为是调和级数的,所以最后的时间复杂度为\(O(n\ln n+nlogn)\)
代码实现非常简单
code:
#include<bits/stdc++.h>
#define N 400050
using namespace std;
struct A {
int l, r, len;
} a[N];
int cmp(A x, A y) {
return x.len < y.len;
}
#define lowbit(x) (x & -x)
int t[N], n, m;
void update(int x, int y) {
for(; x <= m; x += lowbit(x)) t[x] += y;
}
int query(int x) {
int ret = 0;
for(; x; x -= lowbit(x)) ret += t[x];
return ret;
}
void add(int l, int r) {
update(l, 1), update(r + 1, - 1);
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d%d", &a[i].l, &a[i].r), a[i].len = a[i].r - a[i].l + 1;
sort(a + 1, a + 1 + n, cmp);
int now = 0;
for(int d = 1; d <= m; d ++) {
while(now < n && a[now + 1].len < d) now ++, add(a[now].l, a[now].r);
int ans = n - now;
for(int i = 0; i <= m; i += d)
ans += query(i);
printf("%d\n", ans);
}
return 0;
}