CF765F Souvenirs 题解
CF765F Souvenirs 题解
题目链接:CF765F Souvenirs
题目描述:
qry 正在度假,想给两位队友买纪念品。街道上一共有 \(n\) 家纪念品商店。在第 \(i\) 家店里,qry 可以花 \(a_i\) 美元购买一件纪念品,但每家店最多只能买一件。
为了避免队友互相嫉妒,他希望购买的两件纪念品价格尽可能接近。
qry 总共逛了这条街 \(m\) 次。但在第 \(i\) 天时,只有第 \(l_i\) 到第 \(r_i\) 家店铺开门(听起来很离谱对吧?但为了设计区间查询题目的背景设定也只能这样了)。
对于每次逛街,qry 都想知道在当天开门的店铺中,能买到的两件不同纪念品的最小价格差。
换句话说,对于 qry 的每次逛街,你需要找出满足 \(l_i\le s, t \le r_i,s \ne t\) 时,\(|a_s - a_t|\) 的最小可能值。
输入格式:
第一行,一个整数 \(n\;(2\le n\le 10^5)\)。
第二行,\(n\) 个整数 \(a_1,\cdots, a_n\;(0 \le a_i \le 10^9)\)。
第三行是,一个整数 \(m\;(1 \le m \le 3\times 10^5)\),表示查询次数。
接下来 \(m\) 行,第 \(i\) 行包含两个整数 \(l_i,r_i\),表示第\(i\) 天营业的店铺范围 \((1\le l_i<r_i\le n)\)。
输出格式:
对每个查询输出一行,表示答案。
做法请参考 洛谷P5926 [JSOI2009] 面试的考验 题解 。数据范围略不同,其余完全一致。
本题代码:
#include <bits/stdc++.h>
using namespace std;
// #define int long long
// #define INF 0x3f3f3f3f3f3f3f3f
#define INF 0x3f3f3f3f
typedef pair<int,int> pii;
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define mem(a, x) memset(a, x, sizeof(a));
#define N ((int)(3e5 + 15))
#define Fi first
#define Se second
vector<pii> q[N];
int n, m, a[N], ans[N], tr[N];
int rt, tot, ls[N * 32], rs[N * 32], mx[N * 32];
int lowbit(int x) { return x & (-x); }
void add(int x, int v) {
for(int i = x; i; i -= lowbit(i)) down(tr[i], v);
}
int qry(int x, int r = INF) {
for(int i = x; i <= n; i += lowbit(i)) down(r, tr[i]);
return r; // [x, n]
}
void update(int &at, int l, int r, int x, int v)
{
if(!at) { at = ++tot; }
up(mx[at], v); if(l == r) return; int mid = (l + r) >> 1;
if(x <= mid) update(ls[at], l, mid, x, v); else update(rs[at], mid + 1, r, x, v);
}
int query(int at, int l, int r, int nl, int nr)
{
if(!at || l > nr || r < nl) return 0;
if(nl <= l && r <= nr) return mx[at];
int mid = (l + r) >> 1;
return max(query(ls[at], l, mid, nl, nr), query(rs[at], mid + 1, r, nl, nr));
}
void solve()
{
rt = tot = 0; mem(ls, 0); mem(rs, 0); mem(mx, 0); mem(tr, 0x3f);
for(int i = 1; i <= n; i++)
{
int x = query(rt, 0, INF, a[i], INF);
while(x)
{
add(x, a[x] - a[i]); if(a[x] - a[i] == 0) break;
x = query(rt, 0, INF, a[i], (a[i] + a[x]) / 2);
}
update(rt, 0, INF, a[i], i);
for(pii j : q[i]) down(ans[j.Se], qry(j.Fi));
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
memset(ans, 0x3f, sizeof(ans));
cin >> n; for(int i = 1; i <= n; i++) cin >> a[i];
cin >> m; for(int i = 1, l, r; i <= m; i++) { cin >> l >> r, q[r].push_back({l, i}); }
solve(); for(int i = 1; i <= n; i++) a[i] = INF - a[i]; solve();
for(int i = 1; i <= m; i++) cout << ans[i] << '\n';
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 Q779’s Blog!




