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\n",ans);
75     return 0;
76 }

 

posted @ 2019-01-12 20:46  guapisolo  阅读(185)  评论(0编辑  收藏  举报