[kuangbin]树链剖分 C - Tree

和平常的树链剖分维护边权不同的地方在于对线段树的要求较高

NEGATE 反转区间,也就是a - b 内所有的边权取相反数

而Query询问是最大值,所以也就是维护可取反区间的最大值问题

需要维护的值是区间最大值,区间最小值(反转取件后交换其值),lazy标记(优化加速,标记完全反转最大区间)

int rmax[maxn<<2],rmin[maxn<<2],lazy[maxn<<2];

 对应线段树的push_up和push_down操作也就很稳了(就是维护那几个值)

void pup(int rt)
{
    rmax[rt] = max(rmax[rs] , rmax[ls]);
    rmin[rt] = min(rmin[rs] , rmin[ls]);
}
void pdown(int rt)
{
    if(lazy[rt])
    {
        rmax[ls] = -rmax[ls];
        rmin[ls] = -rmin[ls];
        swap(rmax[ls],rmin[ls]);
        rmax[rs] = -rmax[rs];
        rmin[rs] = -rmin[rs];
        swap(rmax[rs],rmin[rs]);
        lazy[ls] ^= 1;
        lazy[rs] ^= 1;
        lazy[rt] = 0;
    }
}

 有一个要注意的地方就是本题有一个点边权更新问题,需要把lazy标记清空一下

好了其他的就是模板问题了

树链做到这基础的的就差不多了,自我感觉还比较良好——嘿嘿嘿心态嘛

/*
https://vjudge.net/contest/251031#problem/F

像是经典的树链剖分,用一下模板
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define lson rt<<1,left,mid
#define rson rt<<1|1,mid+1,right
#define ls rt<<1
#define rs rt<<1|1
#define mid ((left + right) >> 1)
#define inf (1 << 28)
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 1e3;
int n,m,p;
int V[maxn];
//邻接表
struct node{
    int to,pre;
}e[maxn << 1];
struct road{
    int x,y,v;
}r[maxn<<1];
int id[maxn],cnt;
//线段树
int rmax[maxn<<2],rmin[maxn<<2],lazy[maxn<<2];
//dfs1
int siz[maxn],dep[maxn],fa[maxn],son[maxn];
//dfs2
int top[maxn],num_id[maxn],id_num[maxn];
int tot;
void init()
{
    memset(id,-1,sizeof(id));
    memset(son,0,sizeof(son));
    cnt = tot = 0;
}
void add(int from,int to)
{
    e[cnt].to = to;
    e[cnt].pre = id[from];
    id[from] = cnt++;
}
void dfs1(int now,int f,int depth)
{
    siz[now] = 1;
    fa[now] = f;
    dep[now] = depth;

    for(int i = id[now];~i;i = e[i].pre)
    {
        int to = e[i].to;
        if(to != f)
        {
            dfs1(to,now,depth+1);
            siz[now] += siz[to];
            if(siz[to] > siz[son[now]])
                son[now] = to;
        }
    }
}
void dfs2(int now,int rt)
{
    top[now] = rt;
    num_id[now] = ++tot;
    id_num[tot] = now;

    if(!son[now]) return;

    dfs2(son[now],rt);

    for(int i = id[now];~i;i = e[i].pre)
    {
        int to = e[i].to;
        if(to != son[now] && to != fa[now])
        {
            dfs2(to,to);
        }
    }
}
void pup(int rt)
{
    rmax[rt] = max(rmax[rs] , rmax[ls]);
    rmin[rt] = min(rmin[rs] , rmin[ls]);
}
void pdown(int rt)
{
    if(lazy[rt])
    {
        rmax[ls] = -rmax[ls];
        rmin[ls] = -rmin[ls];
        swap(rmax[ls],rmin[ls]);
        rmax[rs] = -rmax[rs];
        rmin[rs] = -rmin[rs];
        swap(rmax[rs],rmin[rs]);
        lazy[ls] ^= 1;
        lazy[rs] ^= 1;
        lazy[rt] = 0;
    }
}
void build(int rt,int left,int right)
{
    lazy[rt] = 0;
    if(left == right)
    {
        rmax[rt] = V[id_num[left]];
        rmin[rt] = V[id_num[left]];
        return;
    }
    build(lson);
    build(rson);
    pup(rt);
}
void updata(int rt,int left,int right,int l,int r,int k)
{
    if(left == l && right == r)
    {
        rmax[rt] = k;
        rmin[rt] = k;
        lazy[rt] = 0;//就算翻转了也可以清除标记了
        return;
    }

    pdown(rt);

    if(r <= mid)
        updata(lson,l,r,k);
    else if(l > mid)
        updata(rson,l,r,k);
    else
    {
        updata(lson,l,mid,k);
        updata(rson,mid+1,r,k);
    }

    pup(rt);
}
void ne_updata(int rt,int left,int right,int l,int r)
{
    if(l <= left && right <= r)
    {
        lazy[rt] ^= 1;
        rmax[rt] = -rmax[rt];
        rmin[rt] = -rmin[rt];
        swap(rmax[rt],rmin[rt]);
        //cout<<rmax[rt]<<" "<<rmin[rt]<<endl;
        return;
    }
    pdown(rt);

    if(l <= mid)
        ne_updata(lson,l,r);
    if(r > mid)
        ne_updata(rson,l,r);

    pup(rt);
}
void updata_lca(int x,int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]])
                swap(x,y);
        ne_updata(1,1,tot,num_id[top[x]],num_id[x]);
        x = fa[top[x]];
    }
    if(x == y)return;
    if(dep[x] < dep[y])
    {
        swap(x,y);
    }
    ne_updata(1,1,tot,num_id[son[y]],num_id[x]);
    return ;
}
int query(int rt,int left,int right,int l,int r)
{
    int res;
    res = -inf;
    if(l <= left && right <= r)
    {
        return rmax[rt];
    }

    pdown(rt);
    if(l <= mid)
    {
          res = max(res,query(lson,l,r));
    }
    if(r > mid)
    {
        res = max(res,query(rson,l,r));
    }
    return res;
}
int querty_lca(int x,int y)
{
    int res;
    res = -inf;
    //cout<<top[x]<<" "<<top[y]<<endl;
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]])
                swap(x,y);
        res = max(res,query(1,1,tot,num_id[top[x]],num_id[x]));
        x = fa[top[x]];
    }
    if(x == y)return res;
    if(dep[x] < dep[y])
    {
        swap(x,y);
    }
    res = max(res,query(1,1,tot,num_id[son[y]],num_id[x]));
    return res;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();
        int from,to,cost;
        for(int i=1;i<=n-1;i++)
        {
            scanf("%d%d%d",&from,&to,&cost);
            r[i].x = from;
            r[i].y = to;
            r[i].v = cost;
            add(from,to);
            add(to,from);
        }

        dfs1(1,0,1);
        dfs2(1,1);
        for(int i=1;i<=n;++i)
        {
            if(dep[r[i].x] < dep[r[i].y])
                swap(r[i].x,r[i].y);
            V[r[i].x] = r[i].v;
        }
        build(1,1,tot);
        //cout<<sum[4]<<" "<<sum[5]<<" "<<sum[6]<<" "<<sum[7]<<endl;
        char op[10];
        int x,y,z;
        while(1)
        {
            scanf("%s",op);
            if(op[0] == 'Q'){
                scanf("%d%d",&x,&y);
                printf("%d\n",querty_lca(x,y));
            }
            else if(op[0] == 'C')
            {
                scanf("%d%d",&x,&z);
                updata(1,1,tot,num_id[r[x].x],num_id[r[x].x],z);
            }
            else if(op[0] == 'N')
            {
                scanf("%d%d",&x,&y);
                updata_lca(x,y);
            }
            else
            {
                break;
            }
        }
    }
    return 0;
}

 

加油吧!有生活,有代码,不迷失,不深陷,体验生活,享受快乐!

 

posted @ 2018-09-06 22:25  Butterflier  阅读(193)  评论(0编辑  收藏  举报