倒垃圾 题型:双指针,二分

39 阅读1分钟

4480. 倒垃圾 - AcWing题库 用二分更好理解:

image.png

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
const int N = 1e5;
vector<int>x;
vector<PII>a;
vector<int>b;


//找x左边最靠近  x  的垃圾桶
int find1(int c) {
	int l = 0, r = a.size() - 1;
	while (l < r) {
		int mid = l + r + 1 >> 1;
		if (a[mid].first <= c)   //如果mid小于x,说明右边还有更靠近x的
			l = mid;
		else
			r = mid - 1;         //否则就是走多了,往回走
	}
	return l;
}


//找x右边最靠近 x 的垃圾桶
int find2(int c) {
	int l = 0, r = a.size() - 1;
	while (l < r) {
		int mid = l + r >> 1;
		if (a[mid].first >= c)   
			r = mid;
		else
			l = mid + 1;
	}
	return l;
}

void sovel() {
	int n, m;
	cin >> n >> m;

	//输入居民楼和垃圾桶的坐标
	for (int i = 0; i < (n + m); i++) {
		int c;
		cin >> c;
		x.push_back(c);
	}


	//输入居民楼和垃圾桶的标记
	for (int i = 0; i < (n + m); i++) {
		//a存垃圾桶的坐标和垃圾桶被使用的次数,b存居民楼的坐标
		int c;
		cin >> c;
		if (c)
			a.push_back({x[i], 0});
		else
			b.push_back(x[i]);
	}

	for (int i = 0; i < b.size(); i++) {
		int c = b[i];
		int x1 = find1(c), x2 = find2(c);

		if (x1 == x2) { //说明找到的是一个垃圾桶,那就把前面的垃圾桶+1
			a[x1].second += 1;
		} else {
			//看一下哪个坐标距离c更近
			if (abs(c - a[x1].first) <= abs(c - a[x2].first))
				a[x1].second += 1;
			else
				a[x2].second += 1;
		}
	}


	//输出结果
	for (int i = 0; i < a.size(); i++)
		cout << a[i].second << " ";
}

int main() {
	cin.tie(nullptr)->sync_with_stdio(false);
	int t = 1;
	while (t--)
		sovel();

	return 0;
}