CF1635F Closest Pair

CF1635F Closest Pair

xx 递增,考虑维护 ww

考虑匹配,由 ww 大的匹配 ww 小的。

显然,单调,若 ijki\leq j\leq k,若 wk>wjw_k>w_j,那么最优的匹配一定不是 (i,k)(i,k)

故考虑维护每个点 ii,记录左右边第一个满足 wj<wiw_j<w_ijj,分别记作 LiL_iRiR_i,单调栈经典操作。

此时,答案匹配只能是区间中所有 (Li,i)(L_i,i)(i,Ri)(i,R_i) 中最小的了,匹配方案 O(n)\mathcal O(n)

然后将询问按照右端点排序,维护左端点,线段树查询最小值即可。

时间复杂度 O(nlogn)\mathcal O(n\log n)

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define ha putchar(' ')
#define he putchar('\n')

inline int read()
{
	int x = 0, f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-')
			f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return x * f;
}

inline void write(ll x)
{
	if(x < 0)
	{
		putchar('-');
		x = -x;
	}
	if(x > 9)
		write(x / 10);
	putchar(x % 10 + 48);
}

const int _ = 3e5 + 10;
const ll inf = LLONG_MAX;

int n, m, w[_], x[_], L[_], R[_], t, q[_];

ll as[_], tr[_ << 2];

vector<int> d[_];

vector<pair<int, int>> qr[_];

void build(int o, int l, int r)
{
	tr[o] = inf;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(o << 1, l, mid), build(o << 1 | 1, mid + 1, r);
}

void upd(int o, int l, int r, int p, ll v)
{
	if(l == r) return tr[o] = min(tr[o], v), void();
	int mid = (l + r) >> 1;
	if(p <= mid) upd(o << 1, l, mid, p, v);
	else upd(o << 1 | 1, mid + 1, r, p, v);
	tr[o] = min(tr[o << 1], tr[o << 1 | 1]);
}

ll qry(int o, int l, int r, int L, int R)
{
	if(L <= l && r <= R) return tr[o];
	int mid = (l + r) >> 1; ll res = inf;
	if(L <= mid) res = qry(o << 1, l, mid, L, R);
	if(R > mid) res = min(res, qry(o << 1 | 1, mid + 1, r, L, R));
	return res;
}

signed main()
{
	n = read(), m = read();
	for(int i = 1; i <= n; ++i) x[i] = read(), w[i] = read();
	t = 0;
	for(int i = 1; i <= n; ++i)
	{
		while(t && w[q[t]] > w[i]) t--;
		L[i] = q[t];
		q[++t] = i;
	}
	t = 0;
	for(int i = n; i >= 1; --i)
	{
		while(t && w[q[t]] > w[i]) t--;
		R[i] = q[t];
		q[++t] = i;
	}
	for(int i = 1, l, r; i <= m; ++i)
	{
		l = read(), r = read();
		qr[r].push_back({l, i});
	}
	for(int i = 1; i <= n; ++i)
	{
		if(L[i]) d[i].push_back(L[i]);
		if(R[i]) d[R[i]].push_back(i);
	}
	build(1, 1, n);
	for(int i = 1; i <= n; ++i)
	{
		for(int j : d[i]) upd(1, 1, n, j, 1ll * abs(x[i] - x[j]) * (w[i] + w[j]));
		for(pair<int, int> j : qr[i]) as[j.second] = qry(1, 1, n, j.first, i);
	}
	for(int i = 1; i <= m; ++i) write(as[i]), he;
	return 0;
}
posted @ 2022-07-18 14:54  蒟蒻orz  阅读(1)  评论(0编辑  收藏  举报  来源