围栏障碍训练场

题目

传送门

分析

  • 说下题意 题意说完你们应该就都懂了
  • 如果牛在栅栏上,那么他只有当自己在 当前行 的左右端点时才能下降,且只能下降,不能左右移
  • 如果牛在地上,那么他就可以满地乱跑,直到爬上栅栏
  • 对于出口,我们可以把它当作在第一行,也可以当做在第0行

  • 看完题面了,那么这个题就 没啥要说的了
  • d p [ i ] [ 0 / 1 ] 表 示 在 第 i 行 的 左 端 / 右 端 , 到 终 点 的 距 离 dp[i][0/1]表示在第i行的左端/右端,到终点的距离 dp[i][0/1]i/
  • 如果从起点处理的话,不好维护到上面的距离
  • 显然我们按照贪心的思想, 想要最小,那么尽可能让他走空白(这样代价为0),所以我们想知道在这个左端点/右端点下方最近的是第几行拦住了我们一往无前
  • 因为层层刷新,单独检查,所以线段树优化一下就好啦

代码

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
const int m=100000;
struct node{
	int l,r;
	int w,f;
}a[N<<2];
int n;
int ll[30010],rr[30010];
long long dp[30010][3];
inline int read()
{
	int Num=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') {Num=(Num<<3)+(Num<<1)+ch-'0'; ch=getchar();}
	return Num*f;
}
void build(int k,int ll,int rr)
{
	a[k].l=ll,a[k].r=rr;
	if(a[k].l==a[k].r)  return ;
	int mid=(ll+rr)>>1;
	build(k<<1,ll,mid); build(k<<1|1,mid+1,rr);
}
void push(int k)
{
	a[k<<1].w=a[k<<1|1].w=a[k].w;
	a[k<<1].f=a[k<<1|1].f=1; a[k].f=0;
}
void change(int k,int l,int r,int w)
{
	if(l<=a[k].l&&a[k].r<=r)
	{
		a[k].w=w;
		a[k].f=1;
		return;
	}
	if(a[k].f) push(k);
	int mid=(a[k].r+a[k].l)>>1;
	if(mid>=l) change(k<<1,l,r,w);
	if(mid<r) change(k<<1|1,l,r,w);
}
int ask(int k,int l)
{	
	if(a[k].l==a[k].r&&a[k].l==l) return a[k].w;
	int mid=(a[k].l+a[k].r)>>1;
	if(a[k].f) push(k);
	if(mid>=l) return ask(k<<1,l);
	else return ask(k<<1|1,l);
}
int main()
{
	n=read();
	int s=read(); s+=m;
	build(1,1,N);
	ll[0]=m,rr[0]=m;
	for(int i=1;i<=n;i++)
	{
		ll[i]=read(),rr[i]=read(); ll[i]+=m; rr[i]+=m;
		int last_l=ask(1,ll[i]);
		int last_r=ask(1,rr[i]);
		dp[i][0]=min(dp[last_l][0]+abs(ll[last_l]-ll[i]),dp[last_l][1]+abs(rr[last_l]-ll[i]));
		dp[i][1]=min(dp[last_r][0]+abs(ll[last_r]-rr[i]),dp[last_r][1]+abs(rr[last_r]-rr[i]));
		change(1,ll[i],rr[i],i);
	}
	printf("%d ",min(dp[n][0]+abs(ll[n]-s),dp[n][1]+abs(rr[n]-s)));
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值