【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;
}
View Code

 

posted @ 2015-09-12 16:26  Owen_hzt  阅读(231)  评论(0编辑  收藏  举报