zoukankan      html  css  js  c++  java
  • [kuangbin]树链剖分 C

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

    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
    ",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;
    }
    

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

  • 相关阅读:
    南阳ACM 题目811:变态最大值 Java版
    南阳ACM 题目811:变态最大值 Java版
    南阳ACM 题目517:最小公倍数 Java版
    南阳ACM 题目517:最小公倍数 Java版
    Jquery学习总结(4)——高效Web开发的10个jQuery代码片段
    Mysql学习总结(34)——Mysql 彻底解决中文乱码的问题
    MyBatis学习总结(19)——Mybatis传多个参数(三种解决方案)
    Git学习总结(10)——git 常用命令汇总
    Spring MVC学习总结(7)——Spring MVC整合Ehcache缓存框架
    Mysql学习总结(33)——阿里云centos配置MySQL主从复制
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9601509.html
Copyright © 2011-2022 走看看