题意:
每次询问求出区间最接近k的数对应的差。
题解:
离线操作,两次排序,计算两次,第一次将询问和数字根据k从小到大排序,碰到询问只要查询区间的最大值跟定是最靠近k的,相反第二次是从大到小排序,求最小值是最靠近k的,两次计算的值取最小值即可。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<string> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #define B(x) (1<<(x)) using namespace std; typedef long long ll; typedef unsigned long long ull; const int oo = 0x3f3f3f3f; const ll OO = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-9; #define lson rt<<1 #define rson rt<<1|1 void cmax(int& a, int b){ if (b > a)a = b; } void cmin(int& a, int b){ if (b < a)a = b; } void cmax(ll& a, ll b){ if (b > a)a = b; } void cmin(ll& a, ll b){ if (b < a)a = b; } void cmax(double& a, double b){ if (a - b < eps) a = b; } void cmin(double& a, double b){ if (b - a < eps) a = b; } void add(int& a, int b, int mod){ a = (a + b) % mod; } void add(ll& a, ll b, ll mod){ a = (a + b) % mod; } const ll MOD = 1000000007; const int maxn = 210000; struct SegTree{ int l, r, max, min; int mid(){ return (l + r) >> 1; } }tree[maxn << 2]; struct Query{ int l, r, k, id, f; }q[maxn << 1]; int ans[maxn]; void push_up(int rt){ tree[rt].max = max(tree[lson].max, tree[rson].max); tree[rt].min = min(tree[lson].min, tree[rson].min); } void build(int l, int r, int rt){ tree[rt].l = l; tree[rt].r = r; tree[rt].max = -oo; tree[rt].min = oo; if (l == r) return; int mid = (l + r) >> 1; build(l, mid, lson); build(mid + 1, r, rson); push_up(rt); } void update(int p, int v, int rt){ if (tree[rt].l == tree[rt].r&&tree[rt].r == p){ tree[rt].max = tree[rt].min = v; return; } int mid = tree[rt].mid(); if (p <= mid) update(p, v, lson); else if (p >= mid + 1) update(p, v, rson); push_up(rt); } int get_max(int l, int r, int rt){ if (l <= tree[rt].l && tree[rt].r <= r){ return tree[rt].max; } int mid = tree[rt].mid(); int res = -oo; if (l <= mid) cmax(res, get_max(l, r, lson)); if (mid + 1 <= r) cmax(res, get_max(l, r, rson)); return res; } int get_min(int l, int r, int rt){ if (l <= tree[rt].l && tree[rt].r <= r){ return tree[rt].min; } int mid = tree[rt].mid(); int res = oo; if (l <= mid) cmin(res, get_min(l, r, lson)); if (mid + 1 <= r) cmin(res, get_min(l, r, rson)); return res; } bool cmp1(Query q1, Query q2){ if (q1.k == q2.k) return q1.f < q2.f; return q1.k < q2.k; } bool cmp2(Query q1, Query q2){ if (q1.k == q2.k) return q1.f < q2.f; return q1.k > q2.k; } int main(){ //freopen("E:\\read.txt", "r", stdin); int T, n, Q, nn, cas = 1; scanf("%d", &T); while (T--){ scanf("%d %d", &n, &Q); for (int i = 1; i <= n; i++){ scanf("%d", &q[i].k); q[i].l = i; q[i].f = 0; } nn = n; for (int i = 1; i <= Q; i++){ ++nn; scanf("%d %d %d", &q[nn].l, &q[nn].r, &q[nn].k); q[nn].f = 1; q[nn].id = i; } build(1, n, 1); sort(q + 1, q + 1 + nn, cmp1); for (int i = 1; i <= nn; i++){ if (q[i].f == 0) update(q[i].l, q[i].k, 1); else ans[q[i].id] = q[i].k - get_max(q[i].l, q[i].r, 1); } build(1, n, 1); sort(q + 1, q + 1 + nn, cmp2); for (int i = 1; i <= nn; i++){ if (q[i].f == 0) update(q[i].l, q[i].k, 1); else{ int tmp = get_min(q[i].l, q[i].r, 1); if (tmp == oo) continue; cmin(ans[q[i].id], tmp - q[i].k); } } printf("Case #%d:\n", cas++); for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]); } return 0; }