【BZOJ 3387】 线段树= =

57 跨栏训练
为了让奶牛参与运动,约翰建造了 K 个栅栏。每条栅栏可以看做是二维平面上的一条线段,它
们都平行于 X 轴。第 i 条栅栏所覆盖的 X 轴坐标的区间为 [ Ai,Bi ], Y 轴高度就是 i。一开始,奶牛
在坐标 (S,K + 1) 处,它们的家在原点处,所以要想要回家就必须“跨”一些栅栏。
但奶牛们是跨不过栅栏的,它们只能绕过栅栏。在二维平面上,它们只能沿水平和垂直方向移动,
如果前进的道路上出现栅栏,它们就不能前进,必须沿水平方向移动到没有栅栏的地方再前进。奶牛
们希望走的路越短越好,由于在垂直方向上的路程是确定的,你只需要帮它们求出在水平方向的最短
路程就可以了。
输入格式
• 第一行:两个整数 K S, 1 K 50000, 105 S 105
• 第二行到第 N + 1 行:第 i + 1 行有两个整数 Ai Bi105 Ai Bi 105
输出格式
• 单个整数:表示奶牛从起点到终点在水平方向移动的最短总距离
样例输入
4 0
-2 1
-1 2
-3 0
-2 1
样例输出
4
解释
第四个栅栏是最先遇到的,向右移一格绕过
它。为了绕过第二个栅栏,再向右移一格,最后
为了回到原点向左移两格

 

【分析】

  就是,差不多,像是个模拟的东西,如果没有东西挡着你,就不用走了(如果要走,等一下有东西挡着你再走)、

  如果有东西挡着你,就走到栅栏左边或者栅栏右边(不用多走,要是需要多走,等一下再走)

  但是询问区间的话每个点到栅栏左端点需要加的距离是不一样的,所以我们维护的时候不是他走的距离,而是他走的距离在加上他走到图的最左边的距离。

  右边也一样。

  就是一个区间修改成INF的操作 以及单点修改 还有区间查询。

 

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 200010
  9 #define Maxk 50010
 10 #define INF 0xfffffff
 11 
 12 int a[Maxk],b[Maxk];
 13 
 14 struct node
 15 {
 16     int l,r,lc,rc,a1,a2;
 17     bool lazy;
 18 }t[Maxn*2];int len;
 19 
 20 int mymin(int x,int y) {return x<y?x:y;}
 21 int mymax(int x,int y) {return x>y?x:y;}
 22 int mn=INF,mx=0;
 23 
 24 int build(int l,int r)
 25 {
 26     int x=++len;
 27     t[x].l=l;t[x].r=r;t[x].a1=t[x].a2=INF;
 28     t[x].lazy=0;
 29     if(l!=r)
 30     {
 31         int mid=(l+r)>>1;
 32         t[x].lc=build(l,mid);
 33         t[x].rc=build(mid+1,r);
 34     }
 35     return x;
 36 }
 37 
 38 void upd(int x)
 39 {
 40     if(t[x].lazy==0) return;
 41     if(t[x].l!=t[x].r)
 42     {
 43         int lc=t[x].lc,rc=t[x].rc;
 44         t[lc].lazy=1;t[rc].lazy=1;
 45     }
 46     t[x].a1=t[x].a2=INF;
 47     t[x].lazy=0;
 48 }
 49 
 50 void change(int x,int l,int r)
 51 {
 52     if(l>r) return;
 53     upd(x);
 54     if(t[x].l==l&&t[x].r==r)
 55     {
 56         t[x].lazy=1;
 57         return;
 58     }
 59     int mid=(t[x].l+t[x].r)>>1;
 60     if(r<=mid) change(t[x].lc,l,r);
 61     else if(l>mid) change(t[x].rc,l,r);
 62     else
 63     {
 64         change(t[x].lc,l,mid);
 65         change(t[x].rc,mid+1,r);
 66     }
 67     int lc=t[x].lc,rc=t[x].rc;
 68     upd(lc);upd(rc);
 69     t[x].a1=mymin(t[lc].a1,t[rc].a1);
 70     t[x].a2=mymin(t[lc].a2,t[rc].a2);
 71 }
 72 
 73 void change2(int x,int y,int z)
 74 {
 75     upd(x);
 76     if(t[x].l==t[x].r)
 77     {
 78         t[x].a1=mymin(t[x].a1,z+y);
 79         t[x].a2=mymin(t[x].a2,z+mx-y);
 80         return;
 81     }
 82     int mid=(t[x].l+t[x].r)>>1;
 83     if(y<=mid) change2(t[x].lc,y,z);
 84     else change2(t[x].rc,y,z);
 85     int lc=t[x].lc,rc=t[x].rc;
 86     upd(lc);upd(rc);
 87     t[x].a1=mymin(t[lc].a1,t[rc].a1);
 88     t[x].a2=mymin(t[lc].a2,t[rc].a2);
 89 }
 90 
 91 int query(int x,int l,int r,bool p)
 92 {
 93     if(l>r) return INF;
 94     upd(x);
 95     if(t[x].l==l&&t[x].r==r)
 96     {
 97         if(!p) return t[x].a1;
 98         else return t[x].a2;
 99     }
100     int mid=(t[x].l+t[x].r)>>1;
101     if(r<=mid) return query(t[x].lc,l,r,p);
102     else if(l>mid) return query(t[x].rc,l,r,p);
103     else return mymin(query(t[x].lc,l,mid,p),query(t[x].rc,mid+1,r,p));
104 }
105 
106 int main()
107 {
108     int k,s;
109     scanf("%d%d",&k,&s);
110     for(int i=1;i<=k;i++)
111     {
112         scanf("%d%d",&a[i],&b[i]);
113         mn=mymin(mn,a[i]);
114         mx=mymax(mx,b[i]);
115     }
116     mn=-mn+1;
117     for(int i=1;i<=k;i++) a[i]+=mn,b[i]+=mn;
118     mx+=mn;
119     len=0;
120     build(1,mx);
121     change2(1,0+mn,0);
122     for(int i=1;i<=k;i++)
123     {
124         int n1=query(1,a[i]+1,b[i]-1,0),n2=query(1,a[i]+1,b[i]-1,1);
125         if(n1!=INF) change2(1,a[i],n1-a[i]);
126         if(n2!=INF) change2(1,b[i],n2-(mx-b[i]) );
127         change(1,a[i]+1,b[i]-1);
128         
129     }
130     s+=mn;
131     int ans=mymin(query(1,1,s,1)-(mx-s),query(1,s,mx,0)-s);
132     printf("%d\n",ans);
133     return 0; 
134 }
[BZOJ 3387]

 

2016-10-31 15:17:12

posted @ 2016-10-31 15:12  konjak魔芋  阅读(720)  评论(0编辑  收藏  举报