[NOI2016]区间 - 线段树

将区间按照长度排序,每次将相同长度的区间插入,直到有一个点能被至少m个区间覆盖,这个可以用线段树维护。

这时我们就可以删除长度小的区间直到不满足条件。

重复做就可以了

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <map>
  6 #define LL long long 
  7 
  8 using namespace std;
  9 
 10 inline LL read()
 11 {
 12     LL x = 0, w = 1; char ch = 0;
 13     while(ch < '0' || ch > '9') {
 14         if(ch == '-') {
 15             w = -1;
 16         }
 17         ch = getchar();
 18     }
 19     while(ch >= '0' && ch <= '9') {
 20         x = x * 10 + ch - '0';
 21         ch = getchar();
 22     }
 23     return x * w;
 24 }
 25 
 26 const int MAXN = 5e5 + 10;
 27 
 28 struct interval {
 29     int l, r;
 30     int len;
 31 } inter[MAXN];
 32 
 33 int ans = 2e9;
 34 int N, M;
 35 map<int, int> m;
 36 int tmp[MAXN * 2];
 37 int len;
 38 int it[MAXN][3];
 39 int cnt = 0;
 40 
 41 bool cmp(interval a, interval b)
 42 {
 43     return a.len < b.len;
 44 }
 45 
 46 struct segment {
 47     int maxn;
 48     int lazy;    
 49 } seg[MAXN * 10];
 50 
 51 void pushdown(int x)
 52 {
 53     seg[x * 2].lazy += seg[x].lazy, seg[x * 2 + 1].lazy += seg[x].lazy;
 54     seg[x * 2].maxn += seg[x].lazy, seg[x * 2 + 1].maxn += seg[x].lazy;    
 55     seg[x].lazy = 0;
 56 }
 57 
 58 void pushup(int x)
 59 {
 60     seg[x].maxn = max(seg[x * 2].maxn, seg[x * 2 + 1 ].maxn);
 61 }
 62 
 63 void update(int ul, int ur, int l, int r, int x, int k)
 64 {
 65     if(ul <= l && ur >= r) {
 66         seg[x].maxn += k;
 67         seg[x].lazy += k;
 68         return;
 69     }
 70     int mid = (l + r) >> 1;
 71     pushdown(x);
 72     if(mid >= ul) {
 73         update(ul, ur, l, mid, x * 2, k);
 74     }
 75     if(mid < ur) {
 76         update(ul, ur, mid + 1, r, x * 2 + 1, k);
 77     }
 78     pushup(x);
 79     return;
 80 }
 81 
 82 int main()
 83 {
 84     //cout<<sizeof seg / 1024 / 1024<<endl;
 85     //freopen("inter.in", "r", stdin);
 86     //freopen("iter.out", "w", stdout);
 87     N = read(), M = read();
 88     for(int i = 1; i <= N; i++) {
 89         tmp[i * 2 - 1] = inter[i].l = read(), tmp[i * 2] = inter[i].r = read();
 90         inter[i].len = inter[i].r - inter[i].l + 1;
 91     }
 92     sort(tmp + 1, tmp + 1 + 2 * N);
 93     len = unique(tmp + 1, tmp + 1 + 2 * N) - tmp - 1;
 94     //cout<<len<<endl;
 95     for(int i = 1; i <= len; i++) {
 96         m[tmp[i]] = i;
 97     }
 98     sort(inter + 1, inter + 1 + N, cmp);
 99     /*for(int i = 1; i <= N; i++) {
100         cout<<m[inter[i].l]<<" "<<m[inter[i].r]<<endl;
101     }
102     cout<<endl;
103     /*for(int i = 1; i <= len; i++) {
104         cout<<tmp[i]<<" ";
105     }
106     cout<<endl;*/
107     //return 0;
108     inter[0].len = -1, inter[N + 1].len = 2e9;
109     it[0][0] = 1e9;
110     for(int i = 1; i <= N + 1; i++) {
111         if(inter[i].len != inter[i - 1].len) {
112             it[cnt][1] = i - 1;
113             it[++cnt][0] = i;
114             it[cnt][2] = inter[i].len;
115         }
116     }
117     /*for(int i = 1; i <= cnt; i++) {
118         cout<<it[i][0]<<" "<<it[i][1]<<" "<<it[i][2]<<endl;
119     }
120     cout<<endl;*/
121     int mi = 0, ma = 0;
122     int status = 0;
123     while(mi <= cnt && ma < cnt) {
124         while(seg[1].maxn < M && ma < cnt) {
125             ma++;
126             //cout<<ma<<endl;
127             //cout<<it[ma][0]<<" "<<it[ma][1]<<endl;
128             for(int i = it[ma][0]; i <= it[ma][1]; i++) {
129                 update(m[inter[i].l], m[inter[i].r], 1, len, 1, 1);
130             }        
131         }
132         //cout<<ma<<" "<<seg[1].maxn<<endl;
133         while(seg[1].maxn >= M) {
134             ans = min(ans, it[ma][2] - it[mi][2]);
135             for(int i = it[mi][0]; i <= it[mi][1]; i++) {
136                 update(m[inter[i].l], m[inter[i].r], 1, len, 1, -1);
137             }
138             mi++;
139             //cout<<m[inter[219].l]<<" "<<m[inter[219].r]<<" "<<mi<<" "<<seg[1].maxn<<endl;
140         }
141         //cout<<mi<<endl;
142     }
143     if(ans == 2e9) {
144         ans = -1;
145     }
146     printf("%d\n", ans);
147     return 0;
148 }
View Code

 

转载于:https://www.cnblogs.com/wuenze/p/9255954.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值