Souvenirs
Souvenirs#
首先离线,考虑每一个点维护后面的点和它绝对值的最小值,那么答案就是一段后缀 ,这个可以用树状数组来维护。那么现在的问题就是加入一个数,去更新前面的状态,假设现在加入了 ,我们只考虑的情况,对于是对称的。
找到一个最大的是容易的,用权值线段树维护即可,但暴力去找每个是不优的,去刻画下一个能更新后缀最小值的位置,有条件 ,因为是能更新的。
发现,这样会在的次数下接近。
这样总时间复杂度为,是值域。
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#define IN inline
using namespace std;
const int N = 1e5 + 5, inf = 1e9;
int ls[N * 30], rs[N * 30], f[N * 30], n, Q, a[N], g[N], siz, ans[N << 2];
IN int read() {
int t = 0,res = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
return t ? -res : res;
}
struct qy{int l, r, id;}b[N << 2];
bool cmp(qy x, qy y){return x.r < y.r;}
int lowbit(int x){return x & -x;}
void add(int x, int v){for (; x; x -= lowbit(x)) g[x] = min(g[x], v);}
int getans(int x) {
int res = 1e9;
for (; x <= n; x += lowbit(x)) res = min(res, g[x]);
return res;
}
void update(int &p, int l, int r, int u, int v) {
if (!p) p = ++siz; f[p] = v;
if (l == r) return; int mid = l + r >> 1;
if (u <= mid) update(ls[p], l, mid, u, v);
else update(rs[p], mid + 1, r, u, v);
}
int query(int p, int l, int r, int L, int R) {
if (!p) return 0;
if (L <= l && r <= R) return f[p];
int mid = l + r >> 1, res = 0;
if (L <= mid) res = query(ls[p], l, mid, L, R);
if (R > mid) res = max(res, query(rs[p], mid + 1, r, L, R));
return res;
}
void solve() {
int rt = 0;
for (int i = 1; i <= siz; i++) f[i] = ls[i] = rs[i] = 0;
for (int i = 1; i <= n; i++) g[i] = 1e9;
siz = 0;
for (int i = 1, j = 1; i <= Q; i++) {
while (j <= n && j <= b[i].r) {
int u = query(rt, 0, inf, a[j], inf);
while (u) {
add(u, a[u] - a[j]);
if (a[u] == a[j]) break;
u = query(rt, 0, inf, a[j], (a[j] + a[u]) / 2);
}
update(rt, 0, inf, a[j], j), j++;
}
ans[b[i].id] = min(ans[b[i].id], getans(b[i].l));
}
}
int main() {
n = read();
for (int i = 1; i <= n; i++) a[i] = read();
Q = read();
for (int i = 1; i <= Q; i++) b[i] = qy{read(), read(), i}, ans[i] = inf;
sort(b + 1, b + 1 + Q, cmp), solve();
for (int i = 1; i <= n; i++) a[i] = inf - a[i];
solve();
for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】