BZOJ 4653: [Noi2016]区间

4653: [Noi2016]区间

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 457  Solved: 245
[Submit][Status][Discuss]

Description

在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
 
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
 
求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

Input

第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n
 
接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。
N<=500000,M<=200000,0≤li≤ri≤10^9

Output

只有一行,包含一个正整数,即最小花费。

Sample Input

6 3
3 5
1 2
3 4
2 2
1 5
1 4

Sample Output

2

HINT

 

Source

 
[Submit][Status][Discuss]

 

这个题吧,就先拿每条线段的长度排序,然后枚举一下最短线段,发现最长线段只会单调变长,所以只需要知道当前维护的区间内是否有个合法的X使得X存在于区间内至少M条线段内。这个就是线段树支持区间加减,全局最值(当然要先对所有坐标离散化处理)。

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 template <class T>
  6 inline T Max(const T &a, const T &b)
  7 {
  8     return a > b ? a : b;
  9 }
 10 
 11 template <class T>
 12 inline T Min(const T &a, const T &b)
 13 {
 14     return a < b ? a : b;
 15 }
 16 
 17 inline int nextChar(void)
 18 {
 19     static const int siz = 1 << 20;
 20     
 21     static char buf[siz];
 22     static char *hd = buf + siz;
 23     static char *tl = buf + siz;
 24     
 25     if (hd == tl)
 26         fread(hd = buf, 1, siz, stdin);
 27     
 28     return int(*hd++);
 29 }
 30 
 31 inline int nextInt(void)
 32 {
 33     int r = 0, c = nextChar();
 34     
 35     for (; c < 48; c = nextChar());
 36     for (; c > 47; c = nextChar())
 37         r = r * 10 + c - '0';
 38     
 39     return r;
 40 }
 41 
 42 const int mxn = 500005;
 43 const int mxm = 200005;
 44 
 45 int n, m;
 46 
 47 struct line
 48 {
 49     int l, r, len;
 50 }L[mxn], *ln[mxn];
 51 
 52 inline bool cmp(line *a, line *b)
 53 {
 54     return a->len < b->len;
 55 }
 56 
 57 int map[mxn << 1], tot;
 58 
 59 inline int find(int k)
 60 {
 61     int lt = 1, rt = tot, mid, ans;
 62     
 63     while (lt <= rt)
 64     {
 65         mid = (lt + rt) >> 1;
 66         
 67         if (map[mid] <= k)
 68             lt = mid + 1, ans = mid;
 69         else
 70             rt = mid - 1;
 71     }
 72     
 73     return ans;
 74 }
 75 
 76 const int siz = 4000005;
 77 
 78 int tag[siz];
 79 int max[siz];
 80 
 81 void add(int t, int l, int r, int x, int y, int v)
 82 {
 83     if (l == x && r == y)
 84     {
 85         tag[t] += v;
 86         max[t] += v;
 87     }
 88     else
 89     {
 90         int mid = (l + r) >> 1;
 91         
 92         if (tag[t])
 93         {
 94             add(t << 1, l, mid, l, mid, tag[t]);
 95             add(t << 1 | 1, mid + 1, r, mid + 1, r, tag[t]);
 96             
 97             tag[t] = 0;
 98         }
 99         
100         if (y <= mid)
101             add(t << 1, l, mid, x, y, v);
102         else if (x > mid)
103             add(t << 1 | 1, mid + 1, r, x, y, v);
104         else
105             add(t << 1, l, mid, x, mid, v),
106             add(t << 1 | 1, mid + 1, r, mid + 1, y, v);
107         
108         max[t] = Max(max[t << 1], max[t << 1 | 1]);
109     }
110 }
111 
112 signed main(void)
113 {
114     n = nextInt();
115     m = nextInt();
116     
117     for (int i = 1; i <= n; ++i)
118     {
119         L[i].l = nextInt();
120         L[i].r = nextInt();
121         
122         L[i].len = L[i].r - L[i].l;
123         
124         map[++tot] = L[i].l;
125         map[++tot] = L[i].r;
126         
127         ln[i] = L + i;
128     }
129     
130     std::sort(map + 1, map + tot + 1);
131         
132     {
133         int cnt = 1;
134         
135         for (int i = 2; i <= tot; ++i)
136             if (map[i] != map[cnt])
137                 map[++cnt] = map[i];
138             
139         tot = cnt;
140     }
141     
142     for (int i = 1; i <= n; ++i)
143     {
144         L[i].l = find(L[i].l);
145         L[i].r = find(L[i].r);
146     }
147     
148     std::sort(ln + 1, ln + n + 1, cmp);
149     
150     int ans = 1E9 + 7;
151     
152     {
153         int cnt = 0;
154         
155         for (int i = 1; i <= n; ++i)
156         {
157             while (cnt < n && max[1] < m)
158             {
159                 line *t = ln[++cnt];
160                 
161                 add(1, 1, tot, t->l, t->r, 1);
162             }
163             
164             if (max[1] >= m)
165                 ans = Min(ans, ln[cnt]->len - ln[i]->len);
166             
167             add(1, 1, tot, ln[i]->l, ln[i]->r, -1);
168         }
169     }
170     
171     if (ans == 1E9 + 7)
172         puts("-1");
173     else
174         printf("%d\n", ans);
175 }

 

@Author: YouSiki

 

posted @ 2017-02-23 08:40  YouSiki  阅读(202)  评论(0编辑  收藏  举报