洛谷P1712 区间

题意:给你n个区间,从中选择m个,使得它们有交,且最长与最短区间的差值最小。

解:这道题我想了好多的,nlog²n错的,nlogn错的,最后终于想出nlogn的了......

把区间按照长度排序,然后依次在线段树上加。

如果某一次等于m了,那么一个一个删,删到小于m的时候,更新答案。

证明:那些之前的区间如果想要成为答案,那么必须是和比当前这个还靠前的区间来组成。

这样的话当到这一个时,之前的要么被计算,要么不会更优。故可以删掉。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 const int N = 500010, INF = 0x3f3f3f3f;
 5 
 6 int sum[N << 3], large[N << 3], tag[N << 3], X[N << 1];
 7 
 8 struct ITV {
 9     int r, l, len;
10     inline bool operator <(const ITV &w) const {
11        return len < w.len;
12     }
13 }a[N];
14 
15 inline void pushup(int o) {
16     int ls = o << 1;
17     int rs = ls | 1;
18     sum[o] = sum[ls] + sum[rs];
19     large[o] = std::max(large[ls], large[rs]);
20     return;
21 }
22 
23 inline void pushdown(int l, int r, int o) {
24     if(tag[o]) {
25         int ls = o << 1;
26         int rs = ls | 1;
27         int mid = (l + r) >> 1;
28         tag[ls] += tag[o];
29         tag[rs] += tag[o];
30         sum[ls] += (mid - l + 1) * tag[o];
31         sum[rs] += (r - mid) * tag[o];
32         large[ls] += tag[o];
33         large[rs] += tag[o];
34         tag[o] = 0;
35     }
36     return;
37 }
38 
39 inline void add(int L, int R, int v, int l, int r, int o) {
40     if(L <= l && r <= R) {
41         tag[o] += v;
42         sum[o] += v * (r - l + 1);
43         large[o] += v;
44         return;
45     }
46     pushdown(l, r, o);
47     int mid = (l + r) >> 1;
48     if(L <= mid) {
49         add(L, R, v, l, mid, o << 1);
50     }
51     if(mid < R) {
52         add(L, R, v, mid + 1, r, o << 1 | 1);
53     }
54     pushup(o);
55     return;
56 }
57 
58 int main() {
59 
60     int n, m;
61     scanf("%d%d", &n, &m);
62     for(int i = 1; i <= n; i++) {
63         scanf("%d%d", &a[i].l, &a[i].r);
64         a[i].len = a[i].r - a[i].l;
65         X[i << 1] = a[i].l;
66         X[(i << 1) - 1] = a[i].r;
67     }
68     std::sort(a + 1, a + n + 1);
69     std::sort(X + 1, X + (n << 1) + 1);
70     int t = std::unique(X + 1, X + (n << 1) + 1) - X - 1;
71     int j = 1, ans = INF;
72     for(int i = 1; i <= n; i++) {
73         a[i].l = std::lower_bound(X + 1, X + t + 1, a[i].l) - X;
74         a[i].r = std::lower_bound(X + 1, X + t + 1, a[i].r) - X;
75         add(a[i].l, a[i].r, 1, 1, t, 1);
76         while(large[1] >= m) {
77             add(a[j].l, a[j].r, -1, 1, t, 1);
78             //printf("large[1] = %d  ans = %d \n i = %d j = %d \n", large[1], ans, i, j);
79             ans = std::min(ans, a[i].len - a[j].len);
80             j++;
81         }
82     }
83     if(ans == INF) {
84         ans = -1;
85     }
86     printf("%d\n", ans);
87     return 0;
88 }
AC代码

这个sum其实是不必要的。

然后我还用动态开点写了一发......被卡空间了。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 const int N = 500010, INF = 0x3f3f3f3f;
 5 
 6 int large[N * 31], tag[N * 31], root, ls[N * 31], rs[N * 31], tot;
 7 
 8 struct ITV {
 9     int r, l, len;
10     inline bool operator <(const ITV &w) const {
11        return len < w.len;
12     }
13 }a[N];
14 
15 inline void pushup(int o) {
16     large[o] = std::max(large[ls[o]], large[rs[o]]);
17     return;
18 }
19 
20 inline void pushdown(int l, int r, int o) {
21     if(tag[o]) {
22         int mid = (l + r) >> 1;
23         if(ls[o]) {
24             large[ls[o]] += tag[o];
25             tag[ls[o]] += tag[o];
26         }
27         if(rs[o]) {
28             large[rs[o]] += tag[o];
29             tag[rs[o]] += tag[o];
30         }
31         tag[o] = 0;
32     }
33     return;
34 }
35 
36 inline void add(int L, int R, int v, int l, int r, int &o) {
37     if(!o) {
38         o = ++tot;
39     }
40     if(L <= l && r <= R) {
41         tag[o] += v;
42         large[o] += v;
43         return;
44     }
45     if(!ls[o]) {
46         ls[o] = ++tot;
47     }
48     if(!rs[o]) {
49         rs[o] = ++tot;
50     }
51     pushdown(l, r, o);
52     int mid = (l + r) >> 1;
53     if(L <= mid) {
54         add(L, R, v, l, mid, ls[o]);
55     }
56     if(mid < R) {
57         add(L, R, v, mid + 1, r, rs[o]);
58     }
59     pushup(o);
60     return;
61 }
62 
63 int main() {
64 
65     int n, m, lm = 0;
66     scanf("%d%d", &n, &m);
67     for(int i = 1; i <= n; i++) {
68         scanf("%d%d", &a[i].l, &a[i].r);
69         a[i].len = a[i].r - a[i].l;
70         lm = std::max(lm, a[i].r);
71     }
72     std::sort(a + 1, a + n + 1);
73     int j = 1, ans = INF;
74     for(int i = 1; i <= n; i++) {
75         add(a[i].l, a[i].r, 1, 1, lm, root);
76         while(large[1] >= m) {
77             add(a[j].l, a[j].r, -1, 1, lm, root);
78             //printf("large[1] = %d  ans = %d \n i = %d j = %d \n", large[1], ans, i, j);
79             ans = std::min(ans, a[i].len - a[j].len);
80             j++;
81         }
82     }
83     if(ans == INF) {
84         ans = -1;
85     }
86     printf("%d\n", ans);
87     return 0;
88 }
95分动态开点

 

posted @ 2018-11-30 15:17  huyufeifei  阅读(164)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜