【JZOJ】3187 的士
来源:互联网 发布:寐蚕丝被 知乎 编辑:程序博客网 时间:2024/04/28 13:28
Description
在高速公路上(0<=M<=1e9),路旁有N(N <= 100000)头奶牛,他们的出发地和目的地分别是Xi,Yi。你从高速公路的起点0出发,每次只能载一头奶牛,要把所有奶牛送到目的地,并且最终要到高速公路的尽头M,求最短的路程和。PS.为了最短,我们可以在中途抛下某头奶牛,只要最后每头奶牛都到目的地就行。
Analysis
这题有两个要求:
1、所有奶牛到目的地。
2、最终要到尽头。
注意
首先这个
得到
如果
从0开始走,每一步都把当前所有奶牛带上(由于一次只能带1个所以往返多次带走),带到下一个位置。
如图:
我们可以先开车开到a接上牛A。
然后载着牛A去b接牛B。
由于只能载一头牛,所以我们要在b–>c之间走3趟,去一次,回来,再去一次。
最后载着牛b去d点,牛A已经在c到站了。
这一定是最优的,因为我们已经尽可能地少走每一段路了,要走的都是必须走的。
但是题目可能存在
对于
到这里就是我比赛时候的思路了。
我打了一个堆来维护
其实这个已经无限接近正解了。
但有些特殊情况没有处理到。
对于绿色的牛,是可以搭顺风车回去的。
但是对于粉色的牛,没有顺风车可以搭,只能单独接他到目的地。
由于我们讨论的顺风车搭不上于是就多跑一段路,导致d到e没有被算上。然后就只有60分了。
事后我也加了点特判但是无济于事。我们需要换下想法。
其实对于回来的点也是一样的嘛,如果我们把出发点设为M的话。
我们用
那么对于
如果
如果
对于0的特殊情况讨论一下【其实这样已经不用特殊讨论了,但是最好讨论一下加深一下理解】
最后别忘了我们从0出发到M去,把这两个位置加入离散化然后一起讨论就好了。
不懂的看看代码吧。
#include<cstring>#include<cstdio>#include<algorithm>#include<map>#include<queue>#include<vector>using namespace std;typedef long long LL;const int N = 101000;priority_queue<int , vector<int> , greater<int> > Q;priority_queue<int> Q2;map<int , int> Hash;struct Data{ int x,y;}a[N],b[N];int c[N * 2],id,tot,tot2,td,n,m,mxt;LL P[N * 2],ans,sum[N * 2],sum2[N * 2];bool cmp(Data x , Data y) { return x.x < y.x;}bool cmp2(Data x , Data y) { return x.x > y.x;}void Relable(){ sort(c , c + 1 + td); for (int i = 0 ; i <= td ; i ++) { int p = Hash[c[i]]; if (!p) Hash[c[i]] = ++ id , P[id] = c[i]; else continue; } for (int i = 1 ; i <= tot ; i ++) a[i].x = Hash[a[i].x] , a[i].y = Hash[a[i].y]; for (int i = 1 ; i <= tot2 ; i ++) b[i].x = Hash[b[i].x] , b[i].y = Hash[b[i].y];}void Solve(){ int pos = a[1].x , l = 1; while (a[l].x == pos && l <= tot) Q.push(a[l].y) , ++ l; while (pos <= id) { sum[pos] = Q.size(); pos ++; while (a[l].x == pos && l <= tot) Q.push(a[l ++].y); int p = Q.top(); while (Q.top() <= pos && !Q.empty()) Q.pop(); } pos = b[1].x , l = 1; while (b[l].x == pos && l <= tot2) Q2.push(b[l ++].y); while (pos) { sum2[pos] = Q2.size(); pos --; while (b[l].x == pos && l <= tot2) Q2.push(b[l ++].y); while (Q2.top() >= pos && !Q2.empty()) Q2.pop(); } //此处可以好好恶搞= = 我打了堆比较丑 //sum就是Pre,sum2就是Suf //此处可以不用讨论= = for (int i = 1 ; i < id ; i ++) if (sum[i] && sum2[i + 1]) { if (sum[i] > sum2[i + 1]) ans += (sum[i] * 2 - 1) * (P[i + 1] - P[i]); else ans += (sum2[i + 1] * 2 + 1) * (P[i + 1] - P[i]); } else { if (!sum2[i + 1] && sum[i]) ans += (sum[i] * 2 - 1) * (P[i + 1] - P[i]); if (sum2[i + 1] && !sum[i]) ans += (sum2[i + 1] * 2 + 1) * (P[i + 1] - P[i]); if (!sum2[i + 1] && !sum[i]) ans += (P[i + 1] - P[i]); }}int main(){ freopen("1.in" , "r" , stdin);freopen("1.out" , "w" , stdout); scanf("%d%d" , &n , &m); c[0] = 0; for (int i = 1 ; i <= n ; i ++) { int x,y;scanf("%d%d" , &x , &y); if (x < y && x != y) a[++ tot].x = x , a[tot].y = y , mxt = max(mxt , y); else if (x != y) b[++ tot2].x = x , b[tot2].y = y , mxt = max(mxt , x); if (x != y) c[++ td] = x , c[++ td] = y; } c[++ td] = m; Relable();//离散化 sort(a + 1 , a + 1 + tot , cmp);sort(b + 1 , b + 1 + tot2 , cmp2); Solve(); printf("%I64d\n" , ans); return 0;}
- 【JZOJ】3187 的士
- 的士
- 员工的士气
- 鼓舞自己的士气
- 烦死飞的士速递
- GDOI2016模拟8.18的士
- JZOJ5238【GDOI模拟】的士碰撞
- 【GDOI2018模拟8.7】的士碰撞
- MBA思考模式的上海的士司机
- 高师傅告诉的士大夫似的风格
- c#日期和随机数--》的士发票
- 巧遇北京“的士之星”魏勇
- 【jzoj5238】【GDOI2018模拟8.7】【的士碰撞】
- 【JZOJ5238】【GDOI2018模拟8.7】的士碰撞
- 视频 | 迪拜将推无人驾驶空中的士,亿航已出局?
- 一次乘的士引发的有关项目管理的思考
- 的士在线:手机上的呼车应用
- fv上的士大夫的法规法规法规
- 工具使用,PS万能对齐大法
- spring中集成作业调度
- 浏览器可视区坐标
- hdu2647(拓扑排序)
- HDU 1874 畅通工程续 <裸的迪杰斯特拉算法>
- 【JZOJ】3187 的士
- Go 1.5的并发特性与案例
- SPFA算法模板
- vs2015小要记
- hud-1874畅通工程续(最短路)
- hadoop native本地库问题总结
- Children’s Queue 1297 (大数)
- Java多线程实践之—协作
- MySQL备份