[NOI2016]区间

题目大意:
  有n次操作,每次覆盖数轴上的区间[l,r]。
  现在要你挑出m次操作,使得数轴上有一个整点恰好被覆盖m次,且最大覆盖区间与最小覆盖区间大小之差最小。

思路:
  首先把询问按长度排序,然后用尺取法O(n)枚举左右端点,用线段树维护每个点被覆盖了几次。
  线段树中的修改要离散化,但最后算长度差时还是要按原来的长度算。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 #include<algorithm>
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int inf=0x7fffffff;
13 const int N=500000;
14 struct Modify {
15     int l,r,b,e;
16     bool operator < (const Modify &another) const {
17         return r-l<another.r-another.l;
18     }
19 };
20 Modify mod[N];
21 std::vector<std::pair<int,int> > v;
22 class SegmentTree {
23     #define _left <<1
24     #define _right <<1|1
25     private:
26         int val[N<<3],tag[N<<3];
27         void push_down(const int &p) {
28             tag[p _left]+=tag[p];
29             tag[p _right]+=tag[p];
30             val[p _left]+=tag[p];
31             val[p _right]+=tag[p];
32             tag[p]=0;
33         }
34         void push_up(const int &p) {
35             val[p]=std::max(val[p _left],val[p _right]);
36         }
37     public:
38         void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int &x) {
39             if(b==l&&e==r) {
40                 tag[p]+=x;
41                 val[p]+=x;
42                 return;
43             }
44             push_down(p);
45             const int mid=(b+e)>>1;
46             if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x);
47             if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x);
48             push_up(p);
49         }
50         int max() const {
51             return  val[1];
52         }
53     #undef _left
54     #undef _right
55 };
56 SegmentTree t;
57 int main() {
58     const int n=getint(),m=getint();
59     v.push_back(std::make_pair(-1,-1));
60     for(register int i=0;i<n;i++) {
61         v.push_back(std::make_pair(mod[i].l=getint(),i));
62         v.push_back(std::make_pair(mod[i].r=getint(),i));
63     }
64     int cnt=0;
65     std::sort(v.begin(),v.end());
66     for(register unsigned i=1;i<v.size();i++) {
67         if(v[i].first!=v[i-1].first) cnt++;
68         if(mod[v[i].second].l==v[i].first) mod[v[i].second].b=cnt;
69         if(mod[v[i].second].r==v[i].first) mod[v[i].second].e=cnt;
70     }
71     v.clear();
72     std::sort(&mod[0],&mod[n]);
73     int ans=inf;
74     t.modify(1,1,cnt,mod[0].b,mod[0].e,1);
75     for(register int l=0,r=1;l<r;l++) {
76         while(t.max()<m&&r<n) {
77             t.modify(1,1,cnt,mod[r].b,mod[r].e,1);
78             r++;
79         }
80         if(r==n&&t.max()<m) break;
81         ans=std::min(ans,(mod[r-1].r-mod[r-1].l)-(mod[l].r-mod[l].l));
82         t.modify(1,1,cnt,mod[l].b,mod[l].e,-1);
83     }
84     printf("%d\n",ans!=inf?ans:-1);
85     return 0;
86 }

 

posted @ 2018-01-05 10:26  skylee03  阅读(130)  评论(0编辑  收藏  举报