[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 }