POJ 2374 Fence Obstacle Course 线段树优化DP
2016-08-29 09:54
369 查看
时空隧道
题目大意:
给出一些篱笆,编号为1~n,1号篱笆在最下面,n号篱笆在最上面,给出起点s的坐标,要求牛从起点出发,到达到达n号篱笆下面的地上的0点,求出最小横向路径
分析:
dp方程比较好想,大概就是没一个篱笆可以更新它下面的最近的一个可以直达的篱笆,还是看代码吧:
然后我们发现这是O(n^2)的转移,n<=5W,挂了
然后我们发现,对于每个i所对应的j可以用线段树来维护,大概可以简化为区间覆盖问题:倒着插入区间,更新区间id,查询每个篱笆的左右端点被哪个id覆盖
代码如下:
题目大意:
给出一些篱笆,编号为1~n,1号篱笆在最下面,n号篱笆在最上面,给出起点s的坐标,要求牛从起点出发,到达到达n号篱笆下面的地上的0点,求出最小横向路径
分析:
dp方程比较好想,大概就是没一个篱笆可以更新它下面的最近的一个可以直达的篱笆,还是看代码吧:
f[1][0]=labs(s-a[1]),f[1][1]=labs(b[1]-s); for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++) if(a[i]>=a[j]&&a[i]<=b[j]){ f[j][0]=min(f[j][0],f[i][0]+labs(a[j]-a[i])); f[j][1]=min(f[j][1],f[i][0]+labs(a[i]-b[j])); break; } for(int j=i+1;j<=n;j++) if(b[i]>=a[j]&&b[i]<=b[j]){ f[j][0]=min(f[j][0],f[i][1]+labs(b[i]-a[j])); f[j][1]=min(f[j][1],f[i][1]+labs(b[j]-b[i])); break; } }
然后我们发现这是O(n^2)的转移,n<=5W,挂了
然后我们发现,对于每个i所对应的j可以用线段树来维护,大概可以简化为区间覆盖问题:倒着插入区间,更新区间id,查询每个篱笆的左右端点被哪个id覆盖
代码如下:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define ZERO 100005 #define int long long #define inf 0x3f3f3f3f using namespace std; const int maxn=50000+5,maxm=200000+5; int n,s,a[maxn],b[maxn],f[maxn][2],MAX,MIN; struct Tree{ int l,r,id; }tree[maxm*4]; struct M{ int A,B; }S[maxn]; inline void build(int l,int r,int tr){ tree.l=l,tree .r=r,tree .id=0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,tr<<1),build(mid+1,r,tr<<1|1); } inline void change(int l,int r,int id,int tr){ if(tree .l==l&&tree .r==r){ tree .id=id; return; } int mid=(tree .l+tree .r)>>1; if(tree .id!=-1){ tree[tr<<1].id=tree .id; tree[tr<<1|1].id=tree .id; } if(r<=mid) change(l,r,id,tr<<1); else if(l>mid) change(l,r,id,tr<<1|1); else change(l,mid,id,tr<<1),change(mid+1,r,id,tr<<1|1); if(tree[tr<<1].id!=tree[tr<<1|1].id||tree[tr<<1].id==-1||tree[tr<<1|1].id==-1) tree .id=-1; } inline int query(int pos,int tr){ if(tree .l==tree .r||(tree .l<=pos&&tree .r>=pos&&tree .id!=-1)) return tree .id; int mid=(tree .l+tree .r)>>1; if(tree .id!=-1){ tree[tr<<1].id=tree .id; tree[tr<<1|1].id=tree .id; } if(pos>mid) return query(pos,tr<<1|1); else return query(pos,tr<<1); } signed main(void){ scanf("%lld%lld",&n,&s),MAX=-inf,MIN=inf; memset(f,inf,sizeof(f)); for(int i=n;i>=1;i--) scanf("%lld%lld",&a[i],&b[i]),MAX=max(MAX,b[i]),MIN=min(a[i],MIN); f[1][0]=labs(s-a[1]),f[1][1]=labs(b[1]-s); build(ZERO+MIN,MAX+ZERO,1); for(int i=n;i>=1;i--) S[i].A=query(a[i]+ZERO,1),S[i].B=query(b[i]+ZERO,1),change(a[i]+ZERO,b[i]+ZERO,i,1); for(int i=1;i<n;i++){ int j=S[i].A; if(j!=0) f[j][0]=min(f[j][0],f[i][0]+labs(a[j]-a[i])),f[j][1]=min(f[j][1],f[i][0]+labs(a[i]-b[j])); j=S[i].B; if(j!=0) f[j][0]=min(f[j][0],f[i][1]+labs(b[i]-a[j])),f[j][1]=min(f[j][1],f[i][1]+labs(b[j]-b[i])); } int ans=min(f [0]+labs(a ),f [1]+labs(b )); for(int i=1;i<n;i++){ if(S[i].A==0) ans=min(f[i][0]+labs(a[i]),ans); if(S[i].B==0) ans=min(ans,f[i][1]+labs(b[i])); } cout<<ans<<endl; return 0; }
by >_< neighthorn相关文章推荐
- POJ 2374 Fence Obstacle Course(map优化DP)
- [线段树]POJ 2374 Fence Obstacle Course
- POJ 2374 Fence Obstacle Course
- POJ 2374 Fence Obstacle Course(线段树+动态规划)
- POJ 2374 Fence Obstacle Course
- poj 2374 Fence Obstacle Course
- POJ2374_Fence Obstacle Course
- POJ 2374/bzoj 3387: [Usaco2004 Dec]Fence Obstacle Course栅栏行动
- POJ 2374 Fence Obstacle Course(线段树+动态规划)
- poj2374 Fence Obstacle Course
- poj2374 Fence Obstacle Course(线段树+建图spfa)
- POJ 1821 Fence ★(单调队列优化DP)
- POJ-1821 Fence(单调队列优化DP)
- POJ 1769 Minimizing maximizer (线段树优化dp)
- POJ 3170 线段树优化DP
- pku2374 Fence Obstacle Course
- POJ 1821 Fence(DP+单调队列优化)
- poj 1821 Fence(dp+单调队列优化)
- POJ 1821 Fence ★(单调队列优化DP)
- POJ 2355(区间最大值-zkw线段树优化Dp方程)