BZOJ3387栅栏行动
2017-04-26 09:47
84 查看
首先,很容易想到Dp。设f[i][0]表示第i个栅栏走左边的最短路,f[i][1]表示第i个栅栏走右边的最短路。
所以,我们要找一个刚好在第i个栅栏的左右边界下面的栅栏。如图所示:
则有:
f[i][0] = min(f[k][0] + |Left[i] - Left[k]| , f[k][1] + |Left[i] - Right[k]| )
[b]f[i][1] = min(f[j][0] + |Right[i] - Left[j]| , f[j][1] + |Right[i] - Right[j]| )
[/b]
那么,该怎样求k和j呢?
很容易想到开一个数组,从小到大覆盖。但这样的时间复杂度是O(n^2)的。用线段树区间修改,单点查询就可以了。
附上程序:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <bitset>
#include <fstream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <deque>
#include <vector>
#include <complex>
#include <utility>
using namespace std;
typedef long long LL;
#define INF 0x3fffffff
#define Maxn 100010
int num[Maxn<<1];
int f[Maxn][2];
int n,m;
int a[Maxn],b[Maxn];
#define L(u) u<<1
#define R(u) u<<1|1
struct Tnode{
int l,r;
bool isset;
int set;
};
Tnode tr[Maxn<<3];
void build(int u,int l,int r)
{
tr[u].l = l; tr[u].r = r;
tr[u].isset = true; tr[u].set = 0;
if(l<r)
{
int mid = (l+r)>>1;
build(L(u),l,mid);
build(R(u),mid+1,r);
}
}
void pushdown(int u)
{
if(tr[u].isset)
{
tr[L(u)].isset = tr[R(u)].isset = true;
tr[L(u)].set = tr[R(u)].set = tr[u].set;
tr[u].isset = tr[u].set = 0;
}
}
void update(int u,int l,int r,int val)
{
if(l<=tr[u].l && tr[u].r<=r)
{
tr[u].isset = true;
tr[u].set = val;
return;
}
pushdown(u);
int mid = (tr[u].l+tr[u].r)>>1;
if(mid>=l) update(L(u),l,r,val);
if(mid<r) update(R(u),l,r,val);
}
int query(int u,int p)
{
if(tr[u].l==tr[u].r)
return tr[u].set;
pushdown(u);
int mid = (tr[u].l+tr[u].r)>>1;
if(p<=mid) return query(L(u),p);
else return query(R(u),p);
}
int main()
{
scanf("%d%d",&n,&m);
build(1,1,Maxn<<1);
a[n+1] = b[n+1] = m;
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
int k1,k2;
for(int i=1;i<=n+1;i++)
{
k1 = query(1,a[i]+100005);
k2 = query(1,b[i]+100005);
f[i][0] = min(f[k1][0]+abs(a[i]-a[k1]),f[k1][1]+abs(a[i]-b[k1]));
f[i][1] = min(f[k2][0]+abs(b[i]-a[k2]),f[k2][1]+abs(b[i]-b[k2]));
if(a[i]+1<b[i])
update(1,a[i]+100005+1,b[i]+100005-1,i);
}
printf("%d\n",f[n+1][0]);
return 0;
}
相关文章推荐
- MySQL 优化
- 5分钟了解MySQL5.7对in用法有什么黑科技
- Google排名优化的几个影响因素
- DB2优化(简易版)
- Mysql limit 优化,百万至千万级快速分页 复合索引的引用并应用于轻量级框架
- C#中尾递归的使用、优化及编译器优化
- 对优化Ruby on Rails性能的一些办法的探究
- 优化Ruby脚本效率实例分享
- Redis优化经验总结(必看篇)
- Asp编码优化技巧
- SQLServer性能优化--间接实现函数索引或者Hash索引
- 如何监测和优化OLAP数据库
- mysql -参数thread_cache_size优化方法 小结
- MySQL数据库优化技术之配置技巧总结
- Oracle数据库中SQL语句的优化技巧
- 深入学习SQL Server聚合函数算法优化技巧
- MySQL常见的底层优化操作教程及相关建议
- 详解mysql的limit经典用法及优化实例
- Mysql Limit 分页查询优化详解
- 数据库学习建议之提高数据库速度的十条建议