题目链接:http://poj.org/problem?id=2374
这个题目坑了好久啊,题意看错了,bs自己。
其实不难的,状态方程容易相处来,每个fence只有两种状态,即左边下去和右边下去,如果要知道当前状态的最优情况,就必须知道前面所有状态的最优情况,最坏情况下复杂度O(n^2)。但显然可以发现前面有很多的状态都不能到达当前状态于,因为前面的有些状态被覆盖了,于是我们可以用线段树来优化,在log(n)的时间里找到可以到达当前状态的fence。虽然在log(n)的时间里找出了状态,但是还是有比较多的状态,还可以继续优化。注意到编号为 i 的fence和所有编号为 1,2,,,,i-1 的fence,编号为 i 的fence只能有前面一个到达,因此我们可以倒叙来DP。
1 //STATUS:C++_AC_329MS_4044KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 #include<map> 13 using namespace std; 14 #define LL __int64 15 #define pii pair<int,int> 16 #define Max(a,b) ((a)>(b)?(a):(b)) 17 #define Min(a,b) ((a)<(b)?(a):(b)) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define lson l,mid,rt<<1 20 #define rson mid+1,r,rt<<1|1 21 const int N=50010,M=100000,INF=0x3f3f3f3f,MOD=100000000; 22 const double DNF=100000000000; 23 24 int l[N][2],f[N][2],sta[200010<<2]; 25 int n,s,w,a,b; 26 27 void update(int l,int r,int rt) 28 { 29 if(a<=l && r<=b){ 30 sta[rt]=w; 31 return; 32 } 33 if(sta[rt]>=0){ 34 sta[rt<<1]=sta[rt<<1|1]=sta[rt]; 35 sta[rt]=-1; 36 } 37 int mid=(l+r)>>1; 38 if(a<=mid)update(lson); 39 if(b>mid)update(rson); 40 } 41 42 void query(int l,int r,int rt) 43 { 44 if(sta[rt]!=-1){ 45 w=sta[rt]; 46 return; 47 } 48 int mid=(l+r)>>1; 49 if(a<=mid)query(lson); 50 else query(rson); 51 } 52 53 int main() 54 { 55 // freopen("in.txt","r",stdin); 56 int i,j,ans; 57 while(~scanf("%d%d",&n,&s)) 58 { 59 mem(f,INF); 60 mem(sta,0); 61 for(i=1;i<=n;i++){ 62 scanf("%d%d",&l[i][0],&l[i][1]); 63 l[i][0]+=M;l[i][1]+=M; 64 } 65 f[0][0]=f[0][1]=0; 66 l[0][0]=l[0][1]=M; 67 for(i=1;i<=n;i++){ 68 w=0;a=l[i][0]; 69 query(0,M<<1,1); 70 f[i][0]=Min(f[w][0]+abs(l[i][0]-l[w][0]),f[w][1]+abs(l[i][0]-l[w][1])); 71 w=0;a=l[i][1]; 72 query(0,M<<1,1); 73 f[i][1]=Min(f[w][0]+abs(l[i][1]-l[w][0]),f[w][1]+abs(l[i][1]-l[w][1])); 74 a=l[i][0],b=l[i][1];w=i; 75 update(0,M<<1,1); 76 } 77 78 ans=Min(f[n][0]+abs(s+M-l[n][0]),f[n][1]+abs(s+M-l[n][1])); 79 printf("%d\n",ans); 80 } 81 return 0; 82 }