2017全国多校第9场

一、HDU-6162 Ch’s gift

思路:只要把主席树节点统计个数的意义改为累计所管辖区间的和就行了。剩下的部分就是裸的树上主席树了。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define LOGN 20
#define MAXQ 100010
#define LL long long
typedef struct {
    int to, next;
} Edge;
LL v[MAXN], dv[MAXN * 3], n, q, dvcnt;
LL par[MAXN][LOGN], depth[MAXN];
Edge edges[MAXN * 2];
int head[MAXN], ecnt;

void init() {
    memset(head, -1, sizeof(head));
    ecnt = 0;
    dvcnt = 0;
}

void add(int from, int to) {
    edges[ecnt].to = to;
    edges[ecnt].next = head[from];
    head[from] = ecnt++;
}

void dfs4lca(int root, int f) {
    par[root][0] = f, depth[root] = depth[f] + 1;
    for(int i = head[root]; ~i; i = edges[i].next) {
        int to = edges[i].to;
        if(to != f)dfs4lca(to, root);
    }
}

void prepare4lca() {
    dfs4lca(1, 0);
    for(int d = 0; d + 1 < LOGN; ++d) {
        for(int i = 1; i <= n; ++i) {
            if(par[i][d] == 0)par[i][d + 1] = 0;
            else par[i][d + 1] = par[par[i][d]][d];
        }
    }
}

int lca(int a, int b) {
    if(depth[a] < depth[b])swap(a, b);
    for(int i = LOGN - 1; i >= 0; i--) {
        int dif = depth[a] - depth[b];
        if((dif >> i) & 1)a = par[a][i];
    }
    if(a == b)return a;
    for(int i = LOGN - 1; i >= 0; --i) {
        if(par[a][i] != par[b][i]) {
            a = par[a][i], b = par[b][i];
        }
    }
    return par[a][0];
}

typedef struct {
    struct Node {
        int lch, rch;
        LL val;
    } nodes[MAXN * 20];
    int root[MAXN], ncnt;

    void init() {
        memset(nodes, 0, sizeof(nodes));
        memset(root, 0, sizeof(root));
        ncnt = 0;
    }
private:
    void update0(int& croot, int proot, LL val, int idx, int l, int r) {
        if(croot == 0) {
            croot = ++ncnt;
            nodes[croot].val = nodes[proot].val + val;
        }
        if(l == r)return;
        int mid = (l + r) >> 1;
        if(idx <= mid) {
            nodes[croot].rch = nodes[proot].rch;
            update0(nodes[croot].lch, nodes[proot].lch, val, idx, l, mid);
        } else {
            nodes[croot].lch = nodes[proot].lch;
            update0(nodes[croot].rch, nodes[proot].rch, val, idx, mid + 1, r);
        }
    }
public:
    void insert(int x, LL val, int idx) {
        update0(root[x], root[par[x][0]], val, idx, 1, dvcnt);
    }
private:
    LL query0(int qlrt, int qrrt, int da, int db, int l, int r) {
        if(l >= da && r <= db)return nodes[qrrt].val - nodes[qlrt].val;
        int mid = (l + r) >> 1;
        LL res = 0;
        if(da <= mid)res += query0(nodes[qlrt].lch, nodes[qrrt].lch, da, db, l, mid);
        if(db > mid)res += query0(nodes[qlrt].rch, nodes[qrrt].rch, da, db, mid + 1, r);
        return res;
    }
public:
    LL query(int ql, int qr, int da, int db, bool left_close) {
//        printf("%d %d\n", ql, par[ql][0]);
        if(left_close)return query0(root[par[ql][0]], root[qr], da, db, 1, dvcnt);
        else return query0(root[ql], root[qr], da, db, 1, dvcnt);
    }
} PerSegTree;

struct qqq {
    int ql, qr, a, b;
} qs[MAXQ];

#define indexOf(x) (lower_bound(dv + 1, dv + dvcnt + 1, x) - dv)
PerSegTree pst;
void buildPST(int root, int f) {
    pst.insert(root, v[root], indexOf(v[root]));
    for(int i = head[root]; ~i; i = edges[i].next) {
        int to = edges[i].to;
        if(to != f)buildPST(to, root);
    }
}

template<class T> inline void read(T& x) {
    bool s = 0;
    char t;
    while((t = getchar()) != '-' && (t < '0' || t > '9'));
    if(t == '-')s = 1, t = getchar();
    x = t - '0';
    while((t = getchar()) >= '0' && t <= '9')x = x * 10 + (t ^ 48);
    if(s)x = -x;
}

int main() {
//    freopen("hdu6162.in", "r", stdin);
    int a, b;
    while(cin >> n >> q) {
        pst.init();
        init();
        for(int i = 1; i <= n; ++i)read(v[i]), dv[++dvcnt] = v[i];
        for(int i = 1; i < n; ++i) {
            read(a), read(b);
            add(a, b);
            add(b, a);
        }
        for(int i = 1; i <= q; ++i) {
            read(qs[i].ql), read(qs[i].qr), read(qs[i].a), read(qs[i].b);
            dv[++dvcnt] = qs[i].a;
            dv[++dvcnt] = qs[i].b;
        }
        prepare4lca();
        sort(dv + 1, dv + dvcnt + 1);
        dvcnt = unique(dv + 1, dv + dvcnt + 1) - dv;
        buildPST(1, 0);
        for(int i = 1; i <= q; ++i) {
            int s = qs[i].ql, t = qs[i].qr;
            int ilca = lca(s, t);
            LL sum = pst.query(ilca, s, indexOf(qs[i].a), indexOf(qs[i].b), 1)
                     + pst.query(ilca, t, indexOf(qs[i].a), indexOf(qs[i].b), 0);
            cout << sum << (i == q ? '\n' : ' ');
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dowhile0/p/9222609.html
今日推荐