【bzoj3600】没有人的算术
替罪羊树模版题。
我们发现原式无法比较大小。
用平衡树为每个式子分配一个值,用来比较大小。树上每个节点有l,r,这个值为l+r。左节点为l,mid,右节点同理。这样分配值显然可以比较大小了。
但该平衡树不能旋转,于是用替罪羊树即可。
siz要在好几处修改。。调了好久。。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <cassert> #define Rep(i, x, y) for (int i = x; i <= y; i ++) #define Dwn(i, x, y) for (int i = x; i >= y; i --) #define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex) #define Ar 0.75 #define Lc t[x + x] #define Rc t[x + x + 1] #define u sc[x] using namespace std; typedef unsigned long long LL; const int N = 1000005, M = 2000005; struct node { int x, y; }; struct Sctree { node x; LL w; int lc, rc; } sc[M * 2]; int n, m, t[M], p[M], lp, d[N], qx, tz, ql, qr, rt, ans, siz[M], fl, dm; int Cmp(node a, node b) { if (a.x == b.x && a.y == b.y) return 2; return (sc[ a.x ].w == sc[ b.x ].w) ? sc[ a.y ].w > sc[ b.y ].w : sc[ a.x ].w > sc[ b.x ].w; } int Build(int l, int r, LL lx, LL rx) { if (l > r) return 0; int mid = l + r >> 1, x = p[mid]; LL mx = (lx + rx) / 2; u.w = lx + rx; if (l == r) { siz[x] = 1; u.lc = u.rc = 0; return x; } u.lc = Build(l, mid - 1, lx, mx), u.rc = Build(mid + 1, r, mx, rx); siz[x] = siz[u.lc] + siz[u.rc] + 1; return x; } void Dfs(int x) { if (!x) return ; Dfs(u.lc), p[++ lp] = x, Dfs(u.rc); } void Add(int &x, node y, LL l, LL r, int dth) { if (!x) { d[qx] = x = ++ tz; u.w = l + r, u.x = y, siz[x] = 1; if (dth > -log(n) / log(Ar)) fl = 1; return ; } dm = max(dth, dm); LL mid = (l + r) / 2; int z; if (Cmp(y, u.x) == 1) { Add(u.rc, y, mid, r, dth + 1), z = u.rc; } else if (Cmp(y, u.x) == 2) { d[qx] = x; return ; } else Add(u.lc, y, l, mid, dth + 1), z = u.lc; siz[x] = siz[u.lc] + siz[u.rc] + 1; if (fl && siz[z] > siz[x] * Ar) { lp = 0, Dfs(x); x = Build(1, lp, l, r); fl = 0; } } bool cmp(int x, int y) { return (sc[d[x]].w == sc[d[y]].w) ? (x < y) : (sc[d[x]].w > sc[d[y]].w); } void Modify(int x, int l, int r) { if (l == r) { return ; } int mid = l + r >> 1; if (qx <= mid) Modify(x+x, l, mid); else Modify(x+x+1, mid+1, r); t[x] = cmp(Lc, Rc) ? Lc : Rc; } void Qry(int x, int l, int r) { if (ql <= l && r <= qr) { ans = cmp(ans, t[x]) ? ans : t[x]; return ; } if (ql > r || qr < l) return ; int mid = l + r >> 1; Qry(x+x, l, mid), Qry(x+x+1, mid+1, r); } void Bt(int x, int l, int r) { if (l == r) { t[x] = l; return ; } int mid = l + r >> 1; Bt(x+x, l, mid), Bt(x+x+1, mid+1, r); t[x] = l; } int main() { scanf ("%d%d", &n, &m); Bt(1, 1, n); char ty[3]; Rep(i, 1, m) { scanf ("%s%d%d", ty, &ql, &qr); if (ty[0] == 'C') { scanf ("%d", &qx); Add(rt, (node) { d[ql], d[qr] }, 1, (1LL << 62) - 1, 1); if (fl) while(1); Modify(1, 1, n); } else { ans = ql; Qry(1, 1, n); printf("%d\n", ans); } } return 0; }