码迷,mamicode.com
首页 > 其他好文 > 详细

UOJ222 NOI2016 区间 线段树+FIFO队列

时间:2016-08-01 22:44:39      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:

首先将区间按长度排序后离散化端点(这里的“长度”指的是离散化之前区间的实际长度)

然后模拟一个队列,区间按排好的顺序依次进入,直到某个点被覆盖了M次。之后依次出队,直到所有点都被覆盖小于M次

修改和询问覆盖次数可以用线段树实现

  1 //C++11 code
  2 
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 
  7 const int maxN=500005;
  8 const int inf=0x7f7f7f7f;
  9 
 10 struct Range
 11 {
 12     int left,right;
 13     int len;
 14     void assign(int l,int r) { left=l; right=r; len=r-l; }
 15 };
 16 
 17 struct SegTree
 18 {
 19     struct Node
 20     {
 21         int val=0; //max-val
 22         int tag=0;
 23         int total() { return val+tag; }
 24     };
 25     Node node[maxN<<2];
 26     int size;
 27     int _val;
 28 
 29     void update(int cur,int right)
 30     {
 31         node[cur].val = std::max(node[cur+1].total(),node[right].total());
 32     }
 33     void add(int L,int R,int val)
 34     {
 35         _val=val;
 36         __add(0,L,R+1,0,size);
 37     }
 38     void __add(int cur,int rL,int rR,int nL,int nR)
 39     {
 40         if(rL<=nL && rR>=nR)
 41         {
 42             node[cur].tag+=_val;
 43             return;
 44         }
 45         int mid=(nL+nR)>>1;
 46         int right=cur+((mid-nL)<<1);
 47         if(rL<mid) __add(cur+1,rL,rR,nL,mid);
 48         if(rR>mid) __add(right,rL,rR,mid,nR);
 49         update(cur,right);
 50     }
 51     int askAll() { return node[0].total(); }
 52 };
 53 
 54 Range rg[maxN];
 55 SegTree segt;
 56 
 57 int N,M;
 58 int buf[maxN<<1];
 59 int valNum;
 60 
 61 void input()
 62 {
 63     scanf("%d%d",&N,&M);
 64     int tl,tr;
 65     for(int i=0;i<N;i++)
 66     {
 67         scanf("%d%d",&tl,&tr);
 68         buf[i<<1]=tl;
 69         buf[(i<<1)+1]=tr;
 70         rg[i].assign(tl,tr);
 71     }
 72 }
 73 
 74 void discretize()
 75 {
 76     std::sort(buf,buf+(N<<1));
 77     valNum=std::unique(buf,buf+(N<<1))-buf;
 78     for(int i=0;i<N;i++)
 79     {
 80         rg[i].left=std::lower_bound(buf,buf+valNum,rg[i].left)-buf;
 81         rg[i].right=std::lower_bound(buf,buf+valNum,rg[i].right)-buf;
 82     }
 83 }
 84 
 85 int solve()
 86 {
 87     int res=inf;
 88     auto cmpIdx=[](const Range& A,const Range& B)->bool { return A.len<B.len; };
 89     std::sort(rg,rg+N,cmpIdx);
 90     discretize();
 91     segt.size=valNum;
 92     int head=-1,tail=-1;
 93     while(1)
 94     {
 95         while((++head)<N && segt.askAll()<M)
 96             segt.add(rg[head].left,rg[head].right,1);
 97         if(segt.askAll()<M) break;
 98         else --head;
 99         while(segt.askAll()==M)
100         {
101             ++tail;
102             res=std::min(res,rg[head].len-rg[tail].len);
103             segt.add(rg[tail].left,rg[tail].right,-1);
104         }
105     }
106     return (res==inf)?-1:res;
107 }
108 
109 int main()
110 {
111     input();
112     printf("%d\n",solve());
113     return 0;
114 }

 

UOJ222 NOI2016 区间 线段树+FIFO队列

标签:

原文地址:http://www.cnblogs.com/Onlynagesha/p/5727249.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!