[51nod1671]货物运输

  公元2222年,l国发生了一场战争。
  小Y负责领导工人运输物资。
  其中有m种物资的运输方案,每种运输方案形如li,ri。表示存在一种货物从li运到ri。
  这里有n个城市,第i个城市与第i+1个城市相连(这里1号城市和n号城市并不相连),并且从i号城市走到i+1号或者从i+1号走到i号需要耗费1点时间。
  由于高科技的存在,小Y想到了一种节省时间的好方案。在X号城市与Y号城市之间设立传送站,只要这么做,在X号城市走到Y号城市不需要耗费时间,同样的,从Y号城市走到X号城市也不需要耗费时间。
  但是为了防止混乱,只能设立这么一条传送站。
  现在这些运输方案同时进行,小Y想让最后到达目的地的运输方案时间最短。

  在样例中,存在两条运输方案,分别是1号城市到3号与2号到4号,那么我们在2号城市与3号城市建立传送站,这样运输方案时间最长的只需要1点时间就可以了。
 Input
  第一行两个整数n,m(1<=n,m<=500000)。
  接下来m行,每行两个整数li,ri(1<=li,ri<=n)。(若li=ri,则不需要耗费任何时间)
 Output
  一个数表示答案。

 

 

  依旧是看了题解。。二分答案mid,假设传送站修在X--Y,那么对于每个R-L>mid的方案L-->R,就只能走L-->X-->Y-->R。

  如果L>X,那么abs(R-Y)<=mid-(L-x),即 R-(mid-(L-X)) <=Y<= R+(mid-(L-X))

  可以发现。。只考虑可行性的话,X是可以丢掉的。。。L<=X同理

  那么只要枚举X,记录L<=X的所有方案的区间交,还有L>X的所有方案的区间交。。只要两个区间交非空就合法了。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #define ll long long
 7 #define ui unsigned int
 8 #define ull unsigned long long
 9 const int maxn=500233,inf=1002333333;
10 struct zs{int l,r;}a[maxn];
11 struct zs1{int l,r,l1,r1,l2,r2;}b[maxn];
12 int l1[maxn],r1[maxn];
13 int i,j,k,n,m,mx;
14 ll ans;
15 
16 int ra,fh;char rx;
17 inline int read(){
18     rx=getchar(),ra=0,fh=1;
19     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
20     if(rx=='-')fh=-1,rx=getchar();
21     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
22 }
23 inline int max(int a,int b){return a>b?a:b;}
24 inline int min(int a,int b){return a<b?a:b;}
25 inline void maxs(int &a,int b){if(b>a)a=b;}
26 inline void mins(int &a,int b){if(b<a)a=b;}
27 inline bool check(int mid){
28     int cnt=0,l2,r2;register int i;
29     for(i=1;i<=n;i++)if(a[i].r-a[i].l>mid)
30         cnt++,
31         b[cnt].l=a[i].l,b[cnt].r=a[i].r,
32         b[cnt].l1= a[i].l+a[i].r-mid,b[cnt].r1=-a[i].l+a[i].r+mid,
33         b[cnt].l2=-a[i].l+a[i].r-mid,b[cnt].r2= a[i].l+a[i].r+mid;
34     l1[mx+1]=l2=-inf,r1[mx+1]=r2=inf;int top=cnt;
35     for(i=mx;i;i--){
36         l1[i]=l1[i+1],r1[i]=r1[i+1];
37         while(top&&b[top].l>=i)
38             maxs(l1[i],b[top].l1),mins(r1[i],b[top].r1),top--;
39     }top=1;
40     for(i=1;i<=mx;i++){
41         while(top<=cnt&&b[top].l<=i)
42             maxs(l2,b[top].l2),mins(r2,b[top].r2),top++;
43         if(l1[i]-i<=r1[i]+i&&l2+i<=r2-i)
44             if(!(r1[i]+i<l2+i||(l1[i]-i>r2-i)))
45                 return /*printf("X:%d  %d--%d %d--%d\n",i,l1[i]-i,r1[i]+i,l2+(i),r2-(i)),*/1;
46     }return 0;
47 }
48 
49 bool operator <(zs a,zs b){return a.l<b.l;}
50 int main(){
51     mx=read(),n=read();int l=0,r=0,mid;
52     for(i=1;i<=n;i++){
53         a[i].l=read(),a[i].r=read();
54         if(a[i].l>a[i].r)std::swap(a[i].l,a[i].r);
55         r=max(r,a[i].r-a[i].l);
56     }
57     std::sort(a+1,a+1+n);
58     while(l<r)if(check(mid=l+r>>1))r=mid;else l=mid+1;
59     printf("%d\n",l);
60 }
View Code

 

转载于:https://www.cnblogs.com/czllgzmzl/p/5950633.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值