树链剖分

先粘模板, 然后再粘一个入门题的代码.

#include <cstdio>
#include <algorithm>

#define lson rt<<1
#define rson rt<<1|1

using namespace std;

typedef long long ll;

const ll maxn = 1e5+500;

int qsz, qcnt;
ll date[maxn];
int head[maxn];
int deep[maxn];
int size[maxn];
int  top[maxn];  // 重链的起点. 
int  son[maxn];
int   id[maxn];  //  节点u的dfs序号 
int   rk[maxn];  //  dfs序号为i的节点  如果使用线段树之类的, build里应该使用 rk 
int   pa[maxn];  //  父节点 

//  First dfs is aim to getting son[], size[] and deep[] pa[]
int dfs(int u, int fa) {
    int i, v, sz = 1, t1; 
    deep[u] = deep[fa] + 1;
    son[u] = u; size[u] = 0;
    pa[u] = fa;
    for (i=head[u]; i; i=edge[i].lst) {
        v = edge[i].to;
        if (v == fa) continue;
        t1 = dfs(v, u);
        sz += t1;
        if (size[son[u]] < t1) son[u] = v;
    }
    size[u] = sz;
    return sz;
}

// Second dfs is aim to getting id[] rk[] top[]
void dfs2(int u, int fa, int t) {
    int i, v;
    top[u] = t; id[u] = qcnt; rk[qcnt++] = u; // update top[] id[] rk[]  
    if (son[u] != u) dfs2(son[u], u, t);
    for (i=head[u]; i; i=edge[i].lst) {
        v = edge[i].to;
        if (v == fa || son[u] == v) continue;
        dfs2(v, u, v);  // 轻儿子 top is itself.
    }
}

ll op(int x, int y) {
    int fx = top[x], fy = top[y];
    ll res = 0;
    while (fx != fy) {
         // 比较top的深度  来选择那个节点需要移动
         // 选择深度比较深的节点向上移动.
         // 这儿定义 fy的深度比较深 
        if (deep[fx] > deep[fy]) {  
            swap(fx, fy);
            swap(x, y);    
        }
        res = (res + query(id[fy], id[y], 1)); // query()是你维护方式, 这儿用的线段树维护. 
        y = pa[fy];     // 这条top链已经获取好信息了, 所以应该是 pa[fy] 
        fy = top[y];    // 继续走 
    } 
    // 最后 fx fy在同一条链上.  dfs序深度浅的小, 深度深的大. 
    if (id[x] <= id[y]) res += query(id[x], id[y], 1);
    else res += query(id[y], id[x], 1);
    return res;
}

// 树链剖分要修改某一棵子树, 就是修改这段区间[id[x], id[x]+size[x]-1]   注,size[x]包含x节点. 

int main()
{

    // init 
    qsz = 1; qcnt = 1;
    deep[0] = 0;
    dfs(1, 0); dfs2(1, 0, 1);
 
    
    return 0;
}

 

入门题  HYSBZ - 4034 

#include <cstdio>
#include <algorithm>

#define lson rt<<1
#define rson rt<<1|1

using namespace std;

typedef long long ll;

const ll maxn = 1e5+500;

int qsz, qcnt;
ll date[maxn];
int head[maxn];
int deep[maxn];
int size[maxn];
int  top[maxn];
int  son[maxn];
int   id[maxn];  //  ½ÚµãuµÄdfsÐò 
int   rk[maxn];  //  dfsΪiµÄ½Úµã 
int   pa[maxn];  //  ½ÚµãuµÄ¸¸½Úµã 

struct nobe {
    int to;
    int lst;
}edge[maxn<<1];

inline void add(int u, int v) {
    edge[qsz].to = v;
    edge[qsz].lst = head[u];
    head[u] = qsz++;
}

//  First dfs is aim to getting son[], size[] and deep[] pa[]
int dfs(int u, int fa) {
    int i, v, sz = 1, t1; 
    deep[u] = deep[fa] + 1;
    son[u] = u; size[u] = 0;
    pa[u] = fa;
    for (i=head[u]; i; i=edge[i].lst) {
        v = edge[i].to;
        if (v == fa) continue;
        t1 = dfs(v, u);
        sz += t1;
        if (size[son[u]] < t1) son[u] = v;
    }
    size[u] = sz;
    return sz;
}

// Second dfs is aim to getting id[] rk[] top[]
void dfs2(int u, int fa, int t) {
    int i, v;
    top[u] = t; id[u] = qcnt; rk[qcnt++] = u; // update top[] id[] rk[]  
    if (son[u] != u) dfs2(son[u], u, t);
    for (i=head[u]; i; i=edge[i].lst) {
        v = edge[i].to;
        if (v == fa || son[u] == v) continue;
        dfs2(v, u, v);  // ~~~link top is itself.
    }
}


struct nobe2 {
    int l;
    int r;
    ll val;
    ll lazy;
    void fun(ll jval) {
         val += jval * (r - l + 1);
        lazy += jval;
    }
}te[maxn<<2];

inline void pshup(int rt) {
    te[rt].val = te[lson].val + te[rson].val;
}

void build(int l, int r, int rt) {
    te[rt].l = l; te[rt].r = r;
    te[rt].lazy = 0;
    if (l == r) {
        te[rt].val = date[rk[l]]; // rk[l]
        return ;
    }
    int m = (l + r) >> 1;
    build(l, m, lson);
    build(m+1, r, rson);
    pshup(rt);
}

inline void pshdwn(int rt) {
    if (te[rt].lazy) {
        te[lson].fun(te[rt].lazy);
        te[rson].fun(te[rt].lazy);
        te[rt].lazy = 0;
    }
}

void update(int l, int r, ll val, int rt) {
    if (l>te[rt].r || r<te[rt].l) return ;
    if (l<=te[rt].l && r>=te[rt].r) {
        te[rt].fun(val);
        return ;
    }
    pshdwn(rt);
    update(l, r, val, lson);
    update(l, r, val, rson);
    pshup(rt);
}

ll query(int l, int r, int rt) {
    if (l>te[rt].r || r<te[rt].l) return 0;
    if (l<=te[rt].l && r>=te[rt].r) return te[rt].val;
    pshdwn(rt);
    return  (query(l, r, lson) + query(l, r, rson));
}

ll op2(int x, int y) {
    int fx = top[x], fy = top[y];
    ll res = 0;
    while (fx != fy) {
        if (deep[fx] > deep[fy]) {
            swap(fx, fy);
            swap(x, y);    
        }
        res = (res + query(id[fy], id[y], 1));
        y = pa[fy];
        fy = top[y];
    } 
    if (id[x] <= id[y]) res += query(id[x], id[y], 1);
    else res += query(id[y], id[x], 1);
    return res;
}

void op3(int x, ll z) {
    update(id[x], id[x] + size[x] - 1, z, 1);
}

int main()
{
    int n, m;
    int i, j, u, v, op, x, y;
    ll z;
    // init 
    qsz = 1; qcnt = 1;
    
    scanf("%d%d", &n, &m);
    for (i=1; i<=n; ++i) scanf("%lld", date+i);
    for (i=1; i<n; ++i) {
        scanf("%d%d", &u, &v);
        add(u, v);
        add(v, u);
    }
    
    deep[0] = 0;
    dfs(1, 0); dfs2(1, 0, 1);
    build(1, n, 1);
 
    while (m--) {
        scanf("%d", &op);
        switch (op) {
        case 1:
            scanf("%d%lld", &x, &z);
            update(id[x], id[x], z, 1);
            break;
        case 2:
            scanf("%d%lld", &x, &z);
            op3(x, z);
            break;
        case 3:
            scanf("%d", &x);
            printf("%lld\n", op2(1, x));
            break;                            
        }
    }
    
    return 0;
}

 

posted @ 2018-08-17 08:49  过路人1998  阅读(160)  评论(0编辑  收藏  举报