1 条题解
-
0
模拟和原版做法一样的加边操作,使用可持久化权值线段树,对每个格子能走到的最低海拔位置开桶维护,即可完成优化。优化后的时间复杂度为 ,空间复杂度为 。
#include <bits/stdc++.h> using namespace std; const int K = 250; const int L = K + 12; const int M = K * K + 12; const int N = 4 * K * K + 12; const int P = 16; const int O = 0xffff; const int D = 4 * K * K * P + 2 * O + 12; const int C = 2 * K * K + 12; pair<unsigned short, unsigned short> e[N]; pair<unsigned char, unsigned char> at[M]; unsigned short alt[L][L]; unsigned short eto[M]; int k; int q; int ec = 0; int now = 0; struct U { unsigned short a[D]; unsigned short ll[D]; unsigned short rr[D]; int l[D]; int r[D]; int roots[C]; int ts; int st; void init(int n) { ts = n; st = n; for (int i = 1; i <= n; i++) rr[i] = (1 << P) - 1; for (int i = 1; i <= n; i++) roots[i] = i; } void expand(int b) { if (ll[b] == rr[b]) return; if (l[b] == 0) { ts++; a[ts] = 0; ll[ts] = ll[b]; rr[ts] = (ll[b] + rr[b]) >> 1; l[ts] = 0; r[ts] = 0; l[b] = ts; } if (r[b] == 0) { ts++; a[ts] = 0; ll[ts] = ((ll[b] + rr[b]) >> 1) + 1; rr[ts] = rr[b]; l[ts] = 0; r[ts] = 0; r[b] = ts; } } bool create(int x, int b) { if (ll[b] == x && rr[b] == x) return true; expand(b); int lmid = (ll[b] + rr[b]) >> 1; int rmid = lmid + 1; if (x <= lmid) return create(x, l[b]); if (x >= rmid) return create(x, r[b]); } bool add(int x, int y, int b, int c) { if (b != c) a[b] += a[c] + y; if (b == c) a[b] += y; if (ll[b] == x && rr[b] == x) return true; int lmid = (ll[b] + rr[b]) >> 1; int rmid = lmid + 1; if (x <= lmid) r[b] = r[c]; if (x >= rmid) l[b] = l[c]; expand(b); if (x <= lmid) return add(x, y, l[b], l[c]); if (x >= rmid) return add(x, y, r[b], r[c]); } int get(int l, int r, int b) { if (!b) return 0; if (l == ll[b] && r == rr[b]) return a[b]; int lmid = (ll[b] + rr[b]) >> 1; int rmid = lmid + 1; if (r <= lmid) return get(l, r, this -> l[b]); if (l >= rmid) return get(l, r, this -> r[b]); return get(l, lmid, this -> l[b]) + get(rmid, r, this -> r[b]); } }; U t; struct T { unsigned short x; unsigned short y; unsigned short a; }; struct R { unsigned short ld[M]; unsigned short sz[M]; unsigned short mina[M]; void init() { for (unsigned short i = 1; i <= k * k; i++) { ld[i] = i; sz[i] = 1; } for (unsigned char i = 1; i <= k; i++) for (unsigned char j = 1; j <= k; j++) mina[(i - 1) * k + j] = alt[i][j]; } unsigned short get(unsigned short x) { if (ld[x] == x) return x; ld[x] = get(ld[x]); return ld[x]; } T mrg(int x, int y) { x = this -> get(x); y = this -> get(y); if (x == y) return (T) {O, O, O}; unsigned short xx = sz[x]; unsigned short yy = sz[y]; if (xx < yy) { swap(x, y); swap(xx, yy); } T res; if (mina[x] < mina[y]) res = (T) {mina[x], mina[y], sz[y]}; if (mina[x] > mina[y]) res = (T) {mina[y], mina[x], sz[x]}; ld[y] = x; sz[x] = xx + yy; sz[y] = 0; mina[x] = min(mina[x], mina[y]); mina[y] = O; return res; } }; R rt; int main() { ios::sync_with_stdio(0); cin >> k >> q; for (int i = 1; i <= k; i++) for (int j = 1; j <= k; j++) cin >> alt[i][j]; for (int i = 0; i <= k + 1; i++) alt[0][i] = O; for (int i = 0; i <= k + 1; i++) alt[k + 1][i] = O; for (int i = 0; i <= k + 1; i++) alt[i][0] = O; for (int i = 0; i <= k + 1; i++) alt[i][k + 1] = O; for (int i = 1; i <= k; i++) for (int j = 1; j <= k; j++) at[alt[i][j]] = make_pair(i, j); for (int i = 0; i <= k * k - 1; i++) { int x = at[i].first; int y = at[i].second; if (alt[x][y + 1] < alt[x][y]) { ec++; e[ec] = make_pair((x - 1) * k + y, (x - 1) * k + (y + 1)); } if (alt[x][y - 1] < alt[x][y]) { ec++; e[ec] = make_pair((x - 1) * k + y, (x - 1) * k + (y - 1)); } if (alt[x + 1][y] < alt[x][y]) { ec++; e[ec] = make_pair((x - 1) * k + y, x * k + y); } if (alt[x - 1][y] < alt[x][y]) { ec++; e[ec] = make_pair((x - 1) * k + y, (x - 2) * k + y); } } rt.init(); t.init(2 * k * k - 1); for (int i = 0; i <= O; i++) t.create(i, t.roots[2 * k * k - 1]); for (int i = 0; i <= O; i++) t.add(i, 1, t.roots[2 * k * k - 1], t.roots[2 * k * k - 1]); t.roots[0] = t.roots[2 * k * k - 1]; for (int i = 1; i <= ec; i++) { T res = rt.mrg(e[i].first, e[i].second); if (res.a != O) { now++; t.add(res.y, -res.a, t.roots[2 * now - 1], t.roots[2 * now - 2]); t.add(res.x, res.a, t.roots[2 * now], t.roots[2 * now - 1]); } eto[alt[(e[i].first - 1) / k + 1][(e[i].first - 1) % k + 1]] = now; } for (int i = 1; i <= k * k - 1; i++) eto[i] = max(eto[i], eto[i - 1]); while (q--) { int x; int y; cin >> x >> y; cout << y - t.get(0, x, t.roots[2 * eto[y - 1]]) << endl; } return 0; }
- 1
信息
- ID
- 110
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 9
- 标签
- 递交数
- 25
- 已通过
- 3
- 上传者