首页 > 代码库 > BUPT2017 wintertraining(15) #9

BUPT2017 wintertraining(15) #9

下面不再说明题意了请自行读题,直接放contest链接。

https://vjudge.net/contest/151607

 

A.考虑当火车隔k站一停时

区间长度 >= k 的纪念品一定能买到

区间长度 <k 的纪念品最多覆盖一个停靠的站点

求出 n / k 个点, 每个点上覆盖的纪念品数累加即可

k 从 1 到 m 都需要求

我们只要把纪念品按区间长度排序

然后向后扫就可以了

总复杂度 O(nlog^2n)

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 #define lowbit(x) (x&(-x))
 5 
 6 using std::sort;
 7 
 8 const int maxn = 300010;
 9 
10 int n, m, c[maxn];
11 
12 struct node {
13     int l, r, len;
14     bool operator < (const node &a) const {
15         return len < a.len;
16     }
17 }a[maxn];
18 
19 void add(int i, int x) {
20     while(i <= m) c[i] += x, i += lowbit(i);
21 }
22 
23 int ask(int i) {
24     int ret = 0;
25     while(i > 0) ret += c[i], i -= lowbit(i);
26     return ret;
27 }
28 
29 int main() {
30     scanf("%d %d", &n, &m);
31     for(int i = 1;i <= n;i ++) {
32         scanf("%d %d", &a[i].l, &a[i].r);
33         a[i].r ++, a[i].len = a[i].r - a[i].l;
34     }
35     sort(a + 1, a + n + 1);
36     for(int i = 1, j = 1, ans;i <= m;i ++) {
37         while(j <= n && a[j].len < i) {
38             add(a[j].l, 1);
39             add(a[j].r, -1);
40             j ++;
41         }
42         ans =  n - j + 1;
43         for(int k = i;k <= m;k += i)
44             ans += ask(k);
45         printf("%d\n", ans);
46     }
47 }
View Code

 

B.

BUPT2017 wintertraining(15) #9