下面不再说明题意了请自行读题,直接放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 }
B.
时间: 2024-10-10 17:03:39