https://www.luogu.org/problemnew/show/2234
将权值离散化,以权值为下标建立权值线段树
#include <bits/stdc++.h> using namespace std; const int N = 32780; const int oo = 999999999; #define gc getchar() #define lson jd << 1 #define rson jd << 1 | 1 struct Node_1 {int data, id;} A[N]; struct Node_2 {int l, r, w, Max, Min;} T[N << 2]; int Ask[N], n, Answer, D[N], before, after; inline int read(){ int x = 0, f = 1; char c = gc; while(c < '0' || c > '9') {if(c == '-') f = -1; c = gc;} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x * f; } bool cmp(Node_1 a, Node_1 b) {return a.data < b.data;} void pushup(int jd){ T[jd].w = T[lson].w + T[rson].w; T[jd].Max = max(T[lson].Max, T[rson].Max); T[jd].Min = min(T[lson].Min, T[rson].Min); } void build_tree(int l, int r, int jd){ T[jd].l = l; T[jd].r = r; T[jd].Min = oo - 1; T[jd].Max = -1; if(l == r) return ; int mid = (l + r) >> 1; build_tree(l, mid, lson); build_tree(mid + 1, r, rson); } void Poi_G(int l, int r, int jd, int x){ if(l == r) {T[jd].w = 1; T[jd].Max = l; T[jd].Min = l; return ;} int mid = (l + r) >> 1; if(x <= mid) Poi_G(l, mid, lson, x); else Poi_G(mid + 1, r, rson, x); pushup(jd); } void Sec_Min(int l, int r, int jd, int x, int y){ if(!T[jd].w) return ; if(x <= l && r <= y) {after = min(after, T[jd].Min); return ;} int mid = (l + r) >> 1; if(x <= mid) Sec_Min(l, mid, lson, x, y); if(y > mid) Sec_Min(mid + 1, r, rson, x, y); } void Sec_Max(int l, int r, int jd, int x, int y){ if(!T[jd].w) return ; if(x <= l && r <= y) {before = max(before, T[jd].Max); return ;} int mid = (l + r) >> 1; if(x <= mid) Sec_Max(l, mid, lson, x, y); if(y > mid) Sec_Max(mid + 1, r, rson, x, y); } int main() { n = read(); for(int i = 1; i <= n; i ++) {A[i].data = read(); A[i].id = i;} sort(A + 1, A + n + 1, cmp);//按照权值进行排序 Ask[A[1].id] = 1; D[1] = A[1].data; int Id = 2;//第i次访问的那个点在线段树中的位置 for(int i = 2; i <= n; i ++){ if(A[i].data == A[i - 1].data) continue ; Ask[A[i].id] = Id; D[Id] = A[i].data;//线段树中位置对应的点的权值 Id ++; } Id --; build_tree(1, Id, 1);//建树 Answer += D[Ask[1]];//第1次访问的点在线段树中的位置所对应的权值 Poi_G(1, Id, 1, Ask[1]); for(int i = 2; i <= n; i ++){ if(!Ask[i]) continue ; before = - oo, after = oo; Sec_Max(1, Id, 1, 1, Ask[i]); Sec_Min(1, Id, 1, Ask[i] + 1, Id); if(before == - oo) Answer += D[after] - D[Ask[i]]; else if(after == oo) Answer += D[Ask[i]] - D[before]; else Answer += min(abs(D[Ask[i]] - D[before]), abs(D[Ask[i]] - D[after])); Poi_G(1, Id, 1, Ask[i]); } cout << Answer; return 0; }