• POJ 2376 Cleaning Shifts (线段树优化DP)


    题目大意:给你很多条线段,开头结尾是$[l,r]$,让你覆盖整个区间$[1,T]$,求最少的线段数

    题目传送门

    线段树优化$DP$裸题..

    先去掉所有能被其他线段包含的线段,这种线段一定不在最优解里

    排序,让所有线段构成左右端点位置都递增的排列

    定义$f[i]$表示第$i$条线段,覆盖到第$i$条线段右端点时,需要的最少的线段数

    $f[i]=min(f[j]+1);(j<i,r[j]>=l[i])$

    朴素是$n^2$转移的

    开一棵最小值线段树,记录从$1$覆盖到位置$x$的最少线段数

    每次求$f[i]$就是在线段树里区间查询。然后在$r[i]$位置更新即可

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define N1 25010
     5 #define M1 1000010
     6 #define ll long long
     7 #define dd double
     8 #define inf 233333333
     9 using namespace std;
    10 
    11 int gint()
    12 {
    13     int ret=0,fh=1;char c=getchar();
    14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    16     return ret*fh;
    17 }
    18 
    19 struct SEG{
    20 int mi[M1<<2];
    21 void pushup(int rt){ mi[rt]=min(mi[rt<<1],mi[rt<<1|1]); }
    22 void build(int l,int r,int rt)
    23 {
    24     mi[rt]=inf; if(l==r) return; 
    25     int mid=(l+r)>>1;
    26     build(l,mid,rt<<1); 
    27     build(mid+1,r,rt<<1|1);
    28 }
    29 void update(int x,int l,int r,int rt,int w)
    30 {
    31     if(l==r){ mi[rt]=w; return; }
    32     int mid=(l+r)>>1; 
    33     if(x<=mid) update(x,l,mid,rt<<1,w);
    34     else update(x,mid+1,r,rt<<1|1,w);
    35     pushup(rt);
    36 }
    37 int query(int L,int R,int l,int r,int rt)
    38 {
    39     if(L<=l&&r<=R) return mi[rt];
    40     int mid=(l+r)>>1,ans=inf;
    41     if(L<=mid) ans=min(ans,query(L,R,l,mid,rt<<1));
    42     if(R>mid) ans=min(ans,query(L,R,mid+1,r,rt<<1|1));
    43     return ans;
    44 }
    45 }s;
    46 
    47 struct node{int l,r;}a[N1],tmp[N1];
    48 int cmp(node s1,node s2){ if(s1.l!=s2.l) return s1.l<s2.l; return s1.r>s2.r; }
    49 int n,m,nn;
    50 int f[M1];
    51 
    52 int main()
    53 {
    54     scanf("%d%d",&n,&m);
    55     int i,ma,ans=inf;
    56     for(i=1;i<=n;i++) tmp[i].l=gint(),tmp[i].r=gint();
    57     sort(tmp+1,tmp+n+1,cmp);
    58     for(i=1,ma=0;i<=n;i++)
    59     {
    60         if(tmp[i].l>ma+1){ puts("-1"); return 0; }
    61         if(tmp[i].r>ma) ma=tmp[i].r,a[++nn]=tmp[i];
    62     }
    63     s.build(1,m,1);
    64     f[1]=1; s.update(a[1].r,1,m,1,1); 
    65     if(a[1].r==m){ puts("1"); return 0; }
    66     for(i=2,ma=a[1].r;i<=nn;i++)
    67     {
    68         f[i]=s.query(max(1,a[i].l-1),ma,1,m,1)+1;
    69         s.update(a[i].r,1,m,1,f[i]);
    70         ma=a[i].r;
    71         if(a[i].r==m) ans=f[i];
    72     }
    73     if(ans==inf) puts("-1");
    74     else printf("%d
    ",ans);
    75     return 0;
    76 }
  • 相关阅读:
    安装centos后无法引导启动windows7的解决方法
    Ubuntu14.04 搜索不到WIFI或连接不上的解决方法。
    ubuntu磁盘分区问题
    Cenos7下nginx+mysql+php环境的搭建
    PHP发送邮件
    php使用数据库的并发问题(乐观锁与悲观锁)
    总结一些php的面试题
    遇到高并发一些处理方法
    PHP中9大缓存技术总结
    php并发加锁示例
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10260968.html
Copyright © 2020-2023  润新知