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 }