RiverSheepSHEEP

Souvenirs

奔跑的心634·2023-03-15 21:57·81 次阅读

Souvenirs

Souvenirs#

首先离线,考虑每一个点维护后面的点和它绝对值的最小值,那么答案就是一段后缀 min,这个可以用树状数组来维护。那么现在的问题就是加入一个数,去更新前面的状态,假设现在加入了 ai,我们只考虑j<i,aj>ai的情况,对于aj<ai是对称的。

找到一个最大的j是容易的,用权值线段树维护即可,但暴力去找每个j是不优的,去刻画下一个能更新后缀最小值的位置k,有条件 akai<ajak,因为j是能更新k的。

发现ak<12(ai+aj),这样ak会在O(logV)的次数下接近ai
这样总时间复杂度为O(nlog2V)V是值域。

Code
Copy
#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]); }
posted @   RiverSheep  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
目录