1. 程式人生 > >【題解】ZJOI2007報表統計

【題解】ZJOI2007報表統計

node ret 代碼 會有 truct post main mes update

洛谷傳送門

主要思路大概也是差不多的,對於兩種詢問分別用線段樹與平衡樹來維護。

1.MIN_SORT_GAP:顯然平衡樹簡單操作,來一發前驅、後繼即可。

2.MIN_GAP:這一個我用的是線段樹:可以註意到插入元素的操作,如果是在一個元素之後反復插入,這些元素之間更新出來的最小值是不會發生改變的。只有元素與元素之間會有不斷的插入而導致最小值變大。所以用線段樹單點修改+維護區間min值,相鄰插入值(中間不會再出現新的數字)之間可以直接暴力維護。

代碼如下:

#include <bits/stdc++.h>
using namespace std;
#define INF 99999999999LL
#define
maxn 2000000 #define int long long int n, m, tot, M1 = INF, M2 = INF, a[maxn]; int b[maxn], root; struct tree { int l, r, num; }T[maxn]; struct node { int v, ch[2], fa; }P[maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < 0 || c > 9) { if(c == -
) k = -1; c = getchar();} while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * k; } struct Splay_Balanced_Tree { void rotate(int x) { int f = P[x].fa, gf = P[f].fa; int k = x == P[f].ch[1]; P[x].fa = gf; if(gf) P[gf].ch[f == P[gf].ch[1
]] = x; P[f].ch[k] = P[x].ch[k ^ 1], P[P[x].ch[k ^ 1]].fa = f; P[f].fa = x, P[x].ch[k ^ 1] = f; } void Splay(int x, int goal) { while(P[x].fa != goal) { int f = P[x].fa, gf = P[f].fa; if(gf != goal) (P[f].ch[1] == x) ^ (P[gf].ch[1] == f) ? rotate(x) : rotate(f); rotate(x); } if(goal == 0) root = x; } void ins(int x) { int u = root, ff = 0; while(u && P[u].v != x) { ff = u; u = P[u].ch[P[u].v < x]; } if(!u) { u = ++ tot; P[u].fa = ff; if(ff) P[ff].ch[P[ff].v < x] = u; P[u].v = x; Splay(u, 0); } } void Find(int x) { int u = root; if(!u) return; while(P[u].v != x && P[u].ch[P[u].v < x]) u = P[u].ch[P[u].v < x]; Splay(u, 0); } int next(int x, int k) { Find(x); int u = root; if(P[u].v == x) return P[u].v; if((P[u].v < x && !k) || (P[u].v > x && k)) return P[u].v; u = P[u].ch[k]; while(P[u].ch[k ^ 1]) u = P[u].ch[k ^ 1]; return P[u].v; } }SBT; struct Segament_Tree { void build(int p, int l, int r) { T[p].l = l, T[p].r = r; if(l == r) { T[p].num = abs(a[l] - a[l - 1]); return; } int mid = (l + r) >> 1; build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r); T[p].num = min(T[p << 1].num, T[p << 1 | 1].num); } void update(int p, int x, int num) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l == T[p].r) { T[p].num = num; return; } if(x <= mid) update(p << 1, x, num); else update(p << 1 | 1, x, num); T[p].num = min(T[p << 1].num, T[p << 1 | 1].num); } }SGT; signed main() { n = read(), m = read(); SBT.ins(INF), SBT.ins(- INF); a[0] = a[n + 1] = INF; for(int i = 1; i <= n; i ++) { a[i] = read(); if(i != 1) { int l = SBT.next(a[i], 0), r = SBT.next(a[i], 1); M2 = min(M2, min(abs(l - a[i]), abs(r - a[i]))); } SBT.ins(a[i]); b[i] = a[i]; } SGT.build(1, 1, n); for(int i = 1; i <= m; i ++) { string s; cin >> s; if(s[0] == I) { int x = read(), y = read(); int l = SBT.next(y, 0), r = SBT.next(y, 1); M2 = min(M2, min(abs(l - y), abs(r - y))); SBT.ins(y); M1 = min(M1, abs(b[x] - y)); SGT.update(1, x + 1, abs(a[x + 1] - y)); b[x] = y; } else if(s[4] == G) printf("%lld\n", min(M1, T[1].num)); else printf("%lld\n", M2); } return 0; }

【題解】ZJOI2007報表統計