POJ 3237 Tree(树链剖分模板)

给出一棵树,和3种操作:

1.更改第i条边的权值;

2.更改结点a到结点b所有边的权值为负;

2.查询结点a到结点b所有边的权值的最大值.


把一颗树hash成一维,在数组中,重链上的点一定是连续存储的.作为边剖分型,可以把边挂在儿子结点上,转化成点剖分型.

另外还要注意的时,最后更新至两条路已经更新至拥有LCA时,由于边的特点,LCA(所代表的那条边)不能更新,所以要更新至LCA的下一个重儿子.但是这样会导致一个问题,可能两个点是同一个点,即LCA.这个时候在线段树里面要特判一下.


#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define MAXN 10010
#define INF 0x7ffffff
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

int sz[MAXN], dep[MAXN], son[MAXN], fa[MAXN], top[MAXN], totw;
int c[MAXN], p[MAXN], w[MAXN], rw[MAXN];
char op[12];

struct Edge
{
    int v, id, next;
}ee[MAXN << 1];
int pre[MAXN], tote;

inline void Init()
{
    memset(pre, 0, sizeof(pre));
    top[1] = fa[1] = sz[1] = 1;
    dep[1] = sz[0] = tote = totw = 0;
}

inline void addedge(int u, int v, int id)
{
    tote++;
    ee[tote].v = v;
    ee[tote].id = id;
    ee[tote].next = pre[u];
    pre[u] = tote;
}

void dfs1(int i = 1)
{
    sz[i] = 1, son[i] = 0;
    for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v != fa[i])
    {
        int v = ee[j].v;
        fa[v] = i;
        p[v] = ee[j].id;
        dep[v] = dep[i] + 1;
        dfs1(v);
        sz[i] += sz[v];
        if(sz[v] > sz[son[i]]) son[i] = v;
    }
}

void dfs2(int i = 1)
{
    for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v == son[i])
    {
        w[ee[j].id] = ++totw;
        rw[totw] = ee[j].id;
        top[son[i]] = top[i];
        dfs2(son[i]);
        break;
    }
    for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v != fa[i] && ee[j].v != son[i])
    {
        w[ee[j].id] = ++totw;
        rw[totw] = ee[j].id;
        dfs2(top[ee[j].v] = ee[j].v);
    }
}

int maxc[MAXN << 2], minc[MAXN << 2], rev[MAXN << 2];
void Build(int l = 1, int r = totw, int rt = 1)
{
    rev[rt] = 0;
    if(l >= r)
    {
        maxc[rt] = minc[rt] = c[rw[l]];
        return ;
    }
    int m = (l + r) >> 1;
    Build(lson), Build(rson);
    maxc[rt] = max(maxc[rt << 1], maxc[rt << 1 | 1]);
    minc[rt] = min(minc[rt << 1], minc[rt << 1 | 1]);
}

void Pushdown(int rt)
{
    if(rev[rt])
    {
        rev[rt << 1] ^= 1, rev[rt << 1 | 1] ^= 1;
        swap(maxc[rt << 1], minc[rt << 1]);
        maxc[rt << 1] *= -1, minc[rt << 1] *= -1;
        swap(maxc[rt << 1 | 1], minc[rt << 1 | 1]);
        maxc[rt << 1 | 1] *= -1, minc[rt << 1 | 1] *= -1;
        rev[rt] = 0;
    }
}

int Query(int L, int R, int l = 1, int r = totw, int rt = 1)
{
    if(L > R || R == 0) return -INF;
    if(L <= l && r <= R) return maxc[rt];
    Pushdown(rt);
    int lch = -INF, rch = -INF;
    int m = (l + r) >> 1;
    if(L <= m) lch = Query(L, R, lson);
    if(R  > m) rch = Query(L, R, rson);
    return max(lch, rch);
}

void Update(int p, int k, int l = 1, int r = totw, int rt = 1)
{
    if(l >= r)
    {
        maxc[rt] = minc[rt] = k;
        return ;
    }
    Pushdown(rt);
    int m = (l + r) >> 1;
    if(p <= m) Update(p, k, lson);
    if(p  > m) Update(p, k, rson);
    maxc[rt] = max(maxc[rt << 1], maxc[rt << 1 | 1]);
    minc[rt] = min(minc[rt << 1], minc[rt << 1 | 1]);
}

void Negate(int L, int R, int l = 1, int r = totw, int rt = 1)
{
    if(L > R || R == 0) return ;
    if(L <= l && r <= R)
    {
        rev[rt] ^= 1;
        swap(maxc[rt], minc[rt]);
        maxc[rt] *= -1, minc[rt] *= -1;
        return ;
    }
    Pushdown(rt);
    int m = (l + r) >> 1;
    if(L <= m) Negate(L, R, lson);
    if(R  > m) Negate(L, R, rson);
    maxc[rt] = max(maxc[rt << 1], maxc[rt << 1 | 1]);
    minc[rt] = min(minc[rt << 1], minc[rt << 1 | 1]);
}

int main()
{

    int t, n; scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        Init();
        for(int i = 1; i < n; i++)
        {
            int u, v;
            scanf("%d%d%d",&u,&v,&c[i]);
            addedge(u, v, i);
            addedge(v, u, i);
        }
        dfs1(), dfs2();
        Build();
        while(~scanf("%s", op))
        {
            if(op[0] == 'D') break;
            if(op[0] == 'C')
            {
                int i, v;
                scanf("%d%d", &i, &v);
                Update(w[i], v);
            }
            else
            {
                int a, b, ans = -INF;
                scanf("%d%d", &a, &b);
                while(top[a] != top[b])
                {
                    if(dep[top[a]] < dep[top[b]]) swap(a, b);
                    if(op[0] == 'Q') ans = max(ans, Query(w[p[top[a]]], w[p[a]]));
                    else Negate(w[p[top[a]]], w[p[a]]);
                    a = fa[top[a]];
                }
                if(dep[a] < dep[b]) swap(a, b);
                if(op[0] == 'Q') ans = max(ans, Query(w[p[son[b]]], w[p[a]]));
                else Negate(w[p[son[b]]], w[p[a]]);
                if(op[0] == 'Q') printf("%d\n", ans);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(ACM,—,数据结构)