【BZOJ3387】[Usaco2004 Dec]Fence Obstacle Course栅栏行动 线段树
【BZOJ3387】[Usaco2004 Dec]Fence Obstacle Course栅栏行动
Description
约翰建造了N(1≤N≤50000)个栅栏来与牛同乐.第i个栅栏的z坐标为[Ai.,Bi](-100000≤Ai<Bi≤10^5),y坐标为i.牛棚的外栏即x轴,原点是牛棚的门.奶牛们开始处于(S,N),她们需要回到牛棚的门(下图中用“*’表示).
约翰的初衷是为了给奶牛们练习跳跃,但是奶牛们似乎更愿意四蹄着地,慢慢她沿着栅栏
走.当她们走到栅栏的尽头,就会朝着牛棚的个栏方向(即y轴负方向)行走,直到碰上另一条栅栏或是牛棚外栏.这时候她们便要选择继续向左走,还是向右走.奶牛们希望走的路程最短.由于可方向的路程一定,你只需求出z方向走的最短路程,使奶牛回到原点.
Input
第1行:N,S(-100000≤S≤100000).
第2到N+1行:每行2个整数Ai,Bi,(-100000≤Ai≤Bi≤100000).
Output
最小的x方向的步数
Sample Input
4 0
-2 1
-1 2
-3 0
-2 1
-2 1
-1 2
-3 0
-2 1
Sample Output
4
HINT
题解:本题做法有很多。我是先列了个朴素的方程,设f[i][0/1]表示走到第i个栅栏左/右边界的最小路程,转移如下
然后就根据绝对值分两种情况讨论,每个都建一个线段树维护一下就好了
注意此题从(S,N)开始!
#include <cstdio> #include <iostream> #include <cstring> #define lson x<<1 #define rson x<<1|1 using namespace std; const int maxn=200005; int n,m; int s[maxn<<2][2],t[maxn<<2][2]; void pushdown(int x,int p) { if(t[x][p]) { s[lson][p]=s[rson][p]=1<<30; t[lson][p]=t[rson][p]=1; t[x][p]=0; } } void updata(int l,int r,int x,int a,int b,int p) { if(l==r) { s[x][p]=min(s[x][p],b); return ; } pushdown(x,p); int mid=l+r>>1; if(a<=mid) updata(l,mid,lson,a,b,p); else updata(mid+1,r,rson,a,b,p); s[x][p]=min(s[lson][p],s[rson][p]); } void cover(int l,int r,int x,int a,int b,int p) { if(a<=l&&r<=b) { t[x][p]=1,s[x][p]=1<<30; return ; } pushdown(x,p); int mid=l+r>>1; if(a<=mid) cover(l,mid,lson,a,b,p); if(b>mid) cover(mid+1,r,rson,a,b,p); s[x][p]=min(s[lson][p],s[rson][p]); } int query(int l,int r,int x,int a,int b,int p) { if(a<=l&&r<=b) return s[x][p]; pushdown(x,p); int mid=l+r>>1; if(b<=mid) return query(l,mid,lson,a,b,p); if(a>mid) return query(mid+1,r,rson,a,b,p); return min(query(l,mid,lson,a,b,p),query(mid+1,r,rson,a,b,p)); } int main() { scanf("%d%d",&n,&m); m+=100002; memset(s,0x3f,sizeof(s)); updata(1,maxn,1,100002,-100002,0),updata(1,maxn,1,100002,100002,1); int i,a,b,ta,tb; for(i=1;i<=n;i++) { scanf("%d%d",&a,&b); a+=100002,b+=100002; ta=min(query(1,maxn,1,1,a,0)+a,query(1,maxn,1,a+1,maxn,1)-a); tb=min(query(1,maxn,1,1,b,0)+b,query(1,maxn,1,b+1,maxn,1)-b); updata(1,maxn,1,a,ta-a,0),updata(1,maxn,1,a,ta+a,1); updata(1,maxn,1,b,tb-b,0),updata(1,maxn,1,b,tb+b,1); if(b>a+1) cover(1,maxn,1,a+1,b-1,0),cover(1,maxn,1,a+1,b-1,1); } printf("%d",min(query(1,maxn,1,1,m,0)+m,query(1,maxn,1,m+1,maxn,1)-m)); return 0; }
| 欢迎来原网站坐坐! >原文链接<