POJ 2374

挺水的一道线段树+DP题。可以从底往上添加线段,每添加线段之前查询端点所被覆盖的区间线段。再从最顶往下DP,每次从端点出发,递推覆盖该端点的区间线段的两端的值即可。

 1 #include <cstdio> 
 2 #include <iostream> 
 3 #include <cstring>  
 4 #include <cctype>  
 5 #include <algorithm>  
 6 #define LL __int64
 7 using namespace std; 
 8 
 9 const int N= 200050;
10 const int SN=50010;
11 const int inf=(1<<30);
12 int mark[N*4];
13 int n,s;
14 int dp[SN][2];
15 struct Seg{
16     int l,r;
17     int li,ri;
18 }seg[SN];
19 
20 void PushDown(int rt){
21     if(mark[rt]!=-1){
22         mark[rt<<1]=mark[rt<<1|1]=mark[rt];
23         mark[rt]=-1;
24     }
25 }
26 
27 void update(int rt,int L,int R,int l,int r,int d){
28     if(L<=l&&r<=R){
29         mark[rt]=d;
30         return ;
31     }
32     PushDown(rt);
33     int m=(l+r)>>1;
34     if(L<=m)update(rt<<1,L,R,l,m,d);
35     if(m<R)update(rt<<1|1,L,R,m+1,r,d);
36 }
37 
38 int query(int rt,int index,int l,int r){
39     if(mark[rt]!=-1){
40         return mark[rt];
41     }
42     int m=(l+r)>>1;
43     if(index<=m) return query(rt<<1,index,l,m);
44     else return query(rt<<1|1,index,m+1,r);
45 }
46 
47 int main(){
48     while(scanf("%d%d",&n,&s)!=EOF){
49         int mm=N,mc=-N;
50         memset(mark,-1,sizeof(mark));
51         for(int i=n-1;i>=0;i--){
52             scanf("%d%d",&seg[i].l,&seg[i].r);
53             mm=min(seg[i].l,mm);
54             mc=max(seg[i].r,mc);
55             dp[i][0]=dp[i][1]=inf;
56         }
57         seg[n].l=mm; seg[n].r=mc;
58         mm=abs(mm);
59         dp[n][0]=dp[n][1]=inf;
60         mm++;
61         update(1,1,seg[n].r+mm,1,mc+mm,n);
62         for(int i=n-1;i>=0;i--){
63             seg[i].li=query(1,seg[i].l+mm,1,mc+mm);
64             seg[i].ri=query(1,seg[i].r+mm,1,mc+mm);
65             update(1,seg[i].l+mm,seg[i].r+mm,1,mm+mc,i);
66         }
67         dp[0][0]=abs(seg[0].l-s),dp[0][1]=abs(seg[0].r-s);
68         int ans=inf;
69         int li,ri;
70         for(int i=0;i<n;i++){
71             li=seg[i].li; ri=seg[i].ri;
72             if(li==n){
73                 ans=min(ans,dp[i][0]+abs(seg[i].l-0));
74             }
75             if(ri==n){
76                 ans=min(ans,dp[i][1]+abs(seg[i].r-0));
77             }
78             dp[li][0]=min(dp[li][0],dp[i][0]+abs(seg[li].l-seg[i].l));
79             dp[li][1]=min(dp[li][1],dp[i][0]+abs(seg[li].r-seg[i].l));
80             dp[ri][0]=min(dp[ri][0],dp[i][1]+abs(seg[ri].l-seg[i].r));
81             dp[ri][1]=min(dp[ri][1],dp[i][1]+abs(seg[ri].r-seg[i].r));
82         }
83         printf("%d\n",ans);
84     }
85     return 0;
86 }
View Code

 

posted @ 2015-03-08 23:20  chenjunjie1994  阅读(372)  评论(0编辑  收藏  举报