[BZOJ 1058][ZJOI2007]報表統計
阿新 • • 發佈:2017-07-23
pac int += node 最大值 cnblogs strong new sort
題目:http://www.lydsy.com/JudgeOnline/problem.php?id=1058
題解
方法一:離線+離散化+線段樹.
這個方式的常數太大,會T。我在洛谷跑最後兩個點TLE了,在BZOJRE了。
具體說一下怎麽做吧。首先把所有數離散化,把出現過的絕對值離散化。這樣我們就能得到約n+m個數和n+m個絕對值。然後,維護兩顆線段樹,記錄數據是否出現,並記錄區間出現的最大值和最小值(因為在線段樹上的點是從大到小的,假設我們添加了元素k,然後我們找它的數據排位(下標)),每添加一個元素更新MIN_SORT_GAP的答案。另一顆維護絕對值的出現和消失,需要用到刪除操作。其實就是線段樹模擬平衡樹。
方法二:TREAP
直接開treap,網上有題解用multiset,但是我沒用,於是就練習一下treap,在BZOJ上AC,在洛谷上T了一個點(最好的時候,一般是T最後兩個點).
開兩個treap,一個維護數列出現的元素,一個維護相鄰元素絕對值(有刪除操作).所以我建議應該用multiset.....orz.
代碼一
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 500005; int n, m, a[maxn], bkp[maxn], d[2][maxn*4], md[2], ins[maxn][2]; int mints[maxn*10], maxts[maxn*10], mintg[maxn*10], numg[maxn*10]; void builds(int o, int L, int R) { mints[o] = maxn; maxts[o] = 0; if (L == R) return; builds(o<<1, L, (L+R)>>1); builds((o<<1)|1, ((L+R)>>1)+1, R); } void buildg(into, int L, int R) { mintg[o] = 0x7fffffff; numg[o] = 0; if (L == R) return; buildg(o<<1, L, (L+R)>>1); buildg((o<<1)|1, ((L+R)>>1)+1, R); } int find(int x, int cur) { int l = 1, r = md[cur]; while (l < r) { int mid = (l+r) >> 1; if (d[cur][mid] == x) return mid; if (d[cur][mid] < x) l = mid+1; else r = mid-1; } return l; } void modifys(int o, int L, int R, int p) { if (L == R) { maxts[o] = mints[o] = L; return; } int mid = (L+R) >> 1; int lc = o << 1, rc = lc+1; if (p <= mid) modifys(lc, L, mid, p); else modifys(rc, mid+1, R, p); maxts[o] = max(maxts[lc], maxts[rc]); mints[o] = min(mints[lc], mints[rc]); } void modifyg(int o, int L, int R, int p, int del) { if (L == R) { numg[o] += del; if (numg[o] == 0) mintg[o] = 0x7fffffff; else mintg[o] = d[1][L]; return; } int mid = (L+R) >> 1; int lc = o << 1, rc = lc+1; if (p <= mid) modifyg(lc, L, mid, p, del); else modifyg(rc, mid+1, R, p, del); mintg[o] = min(mintg[lc], mintg[rc]); } int query(int o, int L, int R, int y1, int y2, int cho) { if (y1 <= L && R <= y2) return (cho?mints[o]:maxts[o]); int mid = (L+R) >> 1; int lc = o << 1, rc = lc+1; int _min = 0x7fffffff, _max = 0; if (cho == 0) { if (y1 <= mid) _max = query(lc, L, mid, y1, y2, cho); if (mid+1 <= y2) _max = max(_max, query(rc, mid+1, R, y1, y2, cho)); return _max; } else { if (y1 <= mid) _min = query(lc, L, mid, y1, y2, cho); if (mid+1 <= y2) _min = min(_min, query(rc, mid+1, R, y1, y2, cho)); return _min; } } void zip(int cur) { int mz = 0; int tmp[maxn*4]; for (int i = 1; i <= md[cur]; ++i) if (i == 1 || d[cur][i] != d[cur][i-1]) tmp[++mz] = d[cur][i]; memcpy(d[cur], tmp, sizeof(tmp)); md[cur] = mz; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); memcpy(d[0], a, sizeof(a)); memcpy(bkp, a, sizeof(a)); md[0] = n; md[1] = n-1; for (int i = 2; i <= n; ++i) d[1][i-1] = abs(a[i]-a[i-1]); for (int i = 0; i < m; ++i) { char cmd[20]; scanf("%s", cmd); if (cmd[0] == ‘I‘) { int loci, x; scanf("%d%d", &loci, &x); ins[i][0] = loci; ins[i][1] = x; d[0][++md[0]] = x; d[1][++md[1]] = abs(bkp[loci]-x); bkp[loci] = x; if (loci < n) d[1][++md[1]] = abs(a[loci+1]-x); } else if (cmd[4] == ‘S‘) ins[i][0] = 0; else ins[i][0] = -1; } sort(d[0]+1, d[0]+md[0]+1); sort(d[1]+1, d[1]+md[1]+1); zip(0); d[0][0] = 0x3fffffff; zip(1); builds(1, 1, md[0]); buildg(1, 1, md[1]); int msg = 0x7fffffff; for (int i = 1; i <= n; ++i) { int k = find(a[i], 0); if (i > 1) { msg = min(msg, abs(d[0][k] - d[0][query(1, 1, md[0], 1, k, 0)])); msg = min(msg, abs(d[0][query(1, 1, md[0], k, md[0], 1)] - d[0][k])); } modifys(1, 1, md[0], k); if (i > 1) modifyg(1, 1, md[1], find(abs(a[i]-a[i-1]), 1), 1); } memcpy(bkp, a, sizeof(a)); for (int i = 0; i < m; ++i) if (ins[i][0] > 0) { int loci = ins[i][0]; int k = find(ins[i][1], 0); msg = min(msg, abs(d[0][k] - d[0][query(1, 1, md[0], 1, k, 0)])); msg = min(msg, abs(d[0][query(1, 1, md[0], k, md[0], 1)] - d[0][k])); modifys(1, 1, md[0], k); modifyg(1, 1, md[1], find(abs(ins[i][1]-a[loci]), 1), 1); if (loci < n) { modifyg(1, 1, md[1], find(abs(a[loci]-bkp[loci+1]), 1), -1); modifyg(1, 1, md[1], find(abs(bkp[loci+1]-ins[i][1]), 1), 1); } a[loci] = ins[i][1]; } else if (ins[i][0] == 0) printf("%d\n", msg); else printf("%d\n", mintg[1]); return 0; }
代碼二
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #define INF 0x3fffffff using namespace std; const int maxn = 500005; struct Treap { struct Node { Node *ch[2]; int r, v, cnt; Node() { *this = NULL; } Node(int v) : v(v) { r = rand()/10*rand(); ch[0] = ch[1] = NULL; cnt = 1; } bool operator < (const Node &rhs) const { return r < rhs.r; } int cmp(int x) const { if (x == v) return -1; return x > v; } }*root; void rotate(Node *&o, int d) { Node *k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o; o = k; } void insert(Node *&o, int x) { if (o == NULL) { o = new Node(x); return; } int k = o->cmp(x); if (k == -1) o->cnt++; else { insert(o->ch[k], x); if (o->ch[k]->r > o->r) rotate(o, k^1); } } void remove(Node *&o, int x) { int d = o->cmp(x); if (d == -1) { if (o->cnt == 0 || (--o->cnt) == 0) { if (o->ch[0] == NULL) o = o->ch[1]; else if (o->ch[1] == NULL) o = o->ch[0]; else { int d1 = o->ch[0]->r > o->ch[1]->r; rotate(o, d1); remove(o->ch[d1], x); } } return; } remove(o->ch[d], x); } int finds(Node *o, int x) { if (o == NULL) return INF; int d = o->cmp(x); if (d == -1) return 0; if (o->ch[d] == NULL) return abs(x-o->v); else return min(abs(x-o->v), finds(o->ch[d], x)); } int findmin() { Node *k = root; while (k->ch[0] != NULL) k = k->ch[0]; return k->v; } }mins, ming; int n, m, msg, a[maxn], bkp[maxn]; void read(int &x) { x = 0; char ch; while ((ch = getchar()) < ‘0‘ || ch > ‘9‘); while (ch >= ‘0‘ && ch <= ‘9‘) x = x*10 + ch-‘0‘, ch = getchar(); } int main() { read(n); read(m); msg = INF; for (int i = 1; i <= n; ++i) { read(a[i]); msg = min(msg, mins.finds(mins.root, a[i])); mins.insert(mins.root, a[i]); if (i > 1) ming.insert(ming.root, abs(a[i]-a[i-1])); } memcpy(bkp, a, sizeof(a)); while (m--) { char cmd[20]; scanf("%s", cmd); if (cmd[0] == ‘I‘) { int i, k; read(i); read(k); msg = min(msg, mins.finds(mins.root, k)); mins.insert(mins.root, k); if (i < n) ming.remove(ming.root, abs(bkp[i]-a[i+1])); ming.insert(ming.root, abs(k-bkp[i])); ming.insert(ming.root, abs(k-a[i+1])); bkp[i] = k; } else if (cmd[4] == ‘S‘) printf("%d\n", msg); else printf("%d\n", ming.findmin()); } return 0; }
[BZOJ 1058][ZJOI2007]報表統計