题解 CF1075B 【Taxi drivers and Lyft】

_Cloud_

2020-10-26 22:09:05

Solution

###### 重新用latex渲染了一下 # 目前最快的方法 ## 思路: 开两个数组,类似前缀和与后缀和 $(\text {sumf,sumb})$,一个记录前 $i$ 个节点到第 $i$ 节点最小距离的节点(前缀最优点),一个记录从 $n+m$ 到第 $i$ 节点的最小距离的节点(后缀最优点)。 遍历每一个 $i$,比较 $\text {sumf}$ 与 $\text {sumb}$ 大小即可。$\text {sumf}_0,\text {sumb}_{n+m+1}$附无穷大表示 $0$ 节点之前无司机和 $n+m+1$ 节点后无司机。 注意:因为最后输出的是数组,所以要在节点无穷大的地方特判。 ### $\text {Code}$ ```cpp #include <cstdio> #include <algorithm> using namespace std; const int N = 1e5 + 5; int sumf[N * 2], sumb[N * 2]; int ans[N * 2]; struct Node { int z, s; } a[N * 2]; int main() { int n, m; scanf("%d %d", &n, &m); for (int i = 1; i <= n + m; i++) scanf("%d", &a[i].z); for (int i = 1; i <= n + m; i++) scanf("%d", &a[i].s);//按从小到大给的数据,不用sort sumf[0] = sumb[n + m + 1] = 214748364;//无穷大表示没有司机 for (int i = 1; i <= n + m; i++) {//前缀最优 if (a[i].s == 1) sumf[i] = i; else sumf[i] = sumf[i - 1]; } for (int i = n + m; i >= 1; i--) {//后缀最优 if (a[i].s == 1) sumb[i] = i; else sumb[i] = sumb[i + 1]; } for (int i = 1; i <= n + m; i++) { if (a[i].s == 0) { if (sumf[i] == 214748364 && sumb[i] < 214748364) {//特判,不然会下标越界 ans[sumb[i]]++; continue; } if ((sumb[i] == 214748364 && sumf[i] < 214748364)) {//同上 ans[sumf[i]]++; continue; } if (a[i].z - a[sumf[i]].z <= a[sumb[i]].z - a[i].z) { ans[sumf[i]]++; } else { ans[sumb[i]]++; } } } for (int i = 1; i <= n + m; i++) { if (a[i].s == 1)//是司机就输出 printf("%d ", ans[i]); } return 0; } ``` #### 评测结果: ![非O2](https://cdn.luogu.com.cn/upload/image_hosting/eogystt0.png) PS:当然,这也只是目前最快的,原因是做的人不多。感谢@[做梦想Peach](https://www.luogu.com.cn/user/239030)提供的latex渲染。