zoukankan      html  css  js  c++  java
  • 【题解】Cut the Sequence(贪心区间覆盖)

    【题解】Cut the Sequence(贪心区间覆盖)

    POJ - 3017

    题意:

    给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量。

    题解

    考虑一个这样的贪心:

    先按照左端点排序,若左端点一样则谁长谁在前。现在判无解就方便了,记录一下前缀max即可。然后现在要最小化选择。

    记录一个最右端点(R),一个暴力的办法是暴力循环判断所有线段是否满足条件,这样显然超时,你决定优化一下常数,所以你记录一下从哪个线段开始才(l_i ge R)。你以为你是常数优化,其实你复杂度就对了((O(n)))...

          const int QAQ=2020;
          while(QAQ){
    	    register int l=r+1;
    	    for(register int t=can;t<=n;++t){
    		  if(data[t].l<=l&&data[t].r>=l)
    			r=max(r,data[t].r);
    		  if(data[t].l>r) {can=t;break;}
    	    }
    	    if(l>r)break;
    	    else if(++ans,r>=T) break;
          }
    

    分析一下这个复杂度,首先是can一定会一直变大,并且变大(O(n))的代价是(O(n))的,所以就是(O(n))的。你可能会说跳出那个for循环不一定是由于break,但是如果不是那个break跳掉的话说明不存在更多合法方案了。

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    int n,T,ans,top,r;
    struct LINE{
          int l,r;
          LINE(){l=r=0;}
          LINE(const int&a,const int&b){l=a;r=b;}
    }data[25005];
    
    inline bool cmp(const LINE&a,const LINE&b){
          if(a.l!=b.l) return a.l<b.l;
          return a.r>b.r;
    }
    
    queue < int > q;
    int main(){
    #ifndef ONLINE_JUDGE
          freopen("in.in","r",stdin);
          //freopen("out.out","w",stdout);
    #endif
          int n=qr();T=qr();
          for(register int t=1,t1,t2;t<=n;++t){
    	    t1=qr();t2=qr();
    	    data[t]=LINE(t1,t2);
          }
          sort(data+1,data+n+1,cmp);
          while(r<T){
    	    register int ew=r+1;
    	    for(register int t=1;t<=n;++t)
    		  if(data[t].l<=ew&&data[t].r>=ew)
    			r=max(r,data[t].r);
    		  else if(data[t].l>r){
    			top=t;
    			break;
    		  }
    	    if(ew>r)break;
    	    else ++ans;
          }
          if(r<T) ans=-1;
          cout<<ans<<endl;
          return 0;
    }
    
  • 相关阅读:
    CSS布局之浮动原理
    img中的alt和title的区别
    重绘+重排+项目优化
    事件冒泡、事件捕获和事件委托
    js数组方法总结
    flex布局
    冒泡排序
    函数节流和函数防抖
    从一个url地址最终到页面渲染完成,发生了什么
    如何让网站变灰
  • 原文地址:https://www.cnblogs.com/winlere/p/10990011.html
Copyright © 2011-2022 走看看