hdu3966(树连剖分模板-节点价值建树)

本文详细介绍了裸的树连剖分模板,并以节点价值为切入点,探讨如何构建树形结构。文章提供了AC代码作为示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

裸的树连剖分,做成模板写的

ACcode:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
using namespace std;

typedef long long LL;

const LL LINF = (1LL <<63);
const int INF = 1 << 31;


const int NS = 500010;
const int MS = 19;
const int MOD = 1000000007;

typedef int segValueType;
const int TSIZE = NS;
struct segNode{
    int ls, rs;             //左右儿子的节点ID
    int lid, rid, len;      //节点的左右边界及长度
    segValueType minv, maxv;       //记录子树节点的价值最值
    segValueType sumv;             //记录子树节点的价值和
    segValueType addv;             //记录子树节点的增量

    bool isLeaf()
    {
        return (lid == rid);
    }

    void printData()
    {
    //    cout<<"("<<lid<<","<<rid<<") max = "<<maxv<<" min = "<<minv<<" sum = "<<sumv<<" add = "<<addv<<endl;
        printf("(%3d,%3d) max = %3d min = %3d sum = %3d add = %d\n", lid, rid, maxv, minv, sumv, addv);
    }
};

struct SegmentTree{
    #define lson(x) (x << 1)
    #define rson(x) ((x << 1) + 1)
    #define pmid(l, r) ((l + r) >> 1)

    int maxrt;
    segNode wt[TSIZE << 2];
    segValueType val[TSIZE];


    segValueType cmax(segValueType va, segValueType vb)
    {
        return (va > vb? va : vb);
    }

    segValueType cmin(segValueType va, segValueType vb)
    {
        return (va < vb? va : vb);
    }

    void PushUpUpdate(int rt)
    {
        int ls = wt[rt].ls;
        int rs = wt[rt].rs;

        wt[rt].maxv = cmax(wt[ls].maxv, wt[rs].maxv);
        wt[rt].minv = cmin(wt[ls].minv, wt[rs].minv);

        wt[rt].sumv = wt[ls].sumv + wt[rs].sumv;
    }

    void PushDownUpdate(int rt)
    {
        if(0 != wt[rt].addv)
        {
            int ls = wt[rt].ls;
            int rs = wt[rt].rs;

            segValueType addv = wt[rt].addv;

            wt[ls].addv += addv;
            wt[ls].maxv += addv;
            wt[ls].minv += addv;
            wt[ls].sumv += wt[ls].len * addv;

            wt[rs].addv += addv;
            wt[rs].maxv += addv;
            wt[rs].minv += addv;
            wt[rs].sumv += wt[rs].len * addv;

            wt[rt].addv = 0;
        }
    }

    void build(int rt, int l, int r)
    {
        if(rt > maxrt) maxrt = rt;
 //       printf("(%d,%d,%d)\n", rt, l, r);
        wt[rt].len = r - l + 1;
        wt[rt].lid = l;
        wt[rt].rid = r;
        wt[rt].addv = 0;
        if(l == r)
        {
            wt[rt].ls = -1;
            wt[rt].rs = -1;
            wt[rt].maxv = wt[rt].minv = val[r];
            wt[rt].sumv = val[r];
            return ;
        }
        else
        {
            wt[rt].ls = lson(rt);
            wt[rt].rs = rson(rt);
        }
        int mid = pmid(wt[rt].lid, wt[rt].rid);
        build(lson(rt), l, mid);
        build(rson(rt), mid + 1, r);
        PushUpUpdate(rt);
    }

    void update(int rt, int l, int r, int op, segValueType value)
    {
        if(l <= wt[rt].lid && wt[rt].rid <= r)
        {
            //如果操作为区间增加val
            wt[rt].addv += value;
            wt[rt].maxv += value;
            wt[rt].minv += value;
            wt[rt].sumv += value * wt[rt].len;
            return ;
        }

        if(wt[rt].isLeaf())
        {
            //正常情况是不会进入此判断的
            printf("线段树异常询问:rt = %2d l = %2d r = %2d op = %2d val = %2d\n", rt, l, r, op, value);
            return ;
        }
        PushDownUpdate(rt);

        int mid = pmid(wt[rt].lid, wt[rt].rid);

        if(l <= mid)
        {
            update(lson(rt), l, r, op, value);
        }
        if(r > mid)
        {
            update(rson(rt), l, r, op, value);
        }
        PushUpUpdate(rt);
    }

    segValueType query(int rt, int l, int r, int op)
    {
        if(l <= wt[rt].lid && wt[rt].rid <= r)
        {
            segValueType res;
            if(1 == op)                 //查询最大值
            {
                res = wt[rt].maxv;
            }
            else if(2 == op)            //查询最小值
            {
                res = wt[rt].minv;
            }
            else if(3 == op)            //查询区间和
            {
                res = wt[rt].sumv;
            }
            return res;
        }
        PushDownUpdate(rt);

        int mid = pmid(wt[rt].lid, wt[rt].rid);

        segValueType res;

        if(l > mid)
        {
            res = query(rson(rt), l, r, op);
        }
        else if(r <= mid)
        {
            res = query(lson(rt), l, r, op);
        }
        else
        {
            if(1 == op)                 //查询最大值
            {
                res = cmax(query(lson(rt), l, r, op), query(rson(rt), l, r, op));
            }
            else if(2 == op)            //查询最小值
            {
                res = cmin(query(lson(rt), l, r, op), query(rson(rt), l, r, op));
            }
            else if(3 == op)            //查询区间和
            {
                res = query(lson(rt), l, r, op) + query(rson(rt), l, r, op);
            }
        }
        return res;
    }

    void printNode(int rt)
    {
        printf("rt = %3d", rt);
        wt[rt].printData();
    }

    void printAll()
    {
        for(int i = 1; i <= maxrt; i++)
        {
            if(wt[i].lid > 0)
            {
                printNode(i);
            }
        }
    }
};

const int EDGE_MAX = NS;
struct graphEdge{
    int pst;
    int next;
    int val;
};

struct ForwardStart{
    int top;
    int head[EDGE_MAX];
    graphEdge edge[EDGE_MAX << 1];

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

    //添加一条u->v的边
    void addEdge(int u, int v, int val)
    {
        edge[top].pst = v;
        edge[top].val = val;
        edge[top].next = head[u];
        head[u] = top++;
    }

    void printAll()
    {
        printf("top = %d\n", top);
        for(int i = 1; i < EDGE_MAX; i++)
        {
            if(-1 != head[i])
            {
                printf("head[%2d]'son:%2d", i, edge[head[i]].pst);
                for(int j = edge[head[i]].next; j != -1; j = edge[j].next)
                {
                    printf(",%2d", edge[j].pst);
                }
                puts("");
            }
        }
    }
};

int n, m, q;

struct chainNode{
    int fa;         //父节点ID
    int dep;        //节点深度
    int scnt;       //子树节点总数
    int top;        //重链第一个节点
    int hson;       //重儿子ID
    int tpos;       //节点在线段树中的位置

    void init(int _fa, int _dep)
    {
        fa = _fa;
        dep = _dep;
        scnt = 1;
        hson = -1;

        top = -1;
        tpos = -1;
    }

    void printData()
    {
        printf("fa = %2d dep = %2d scnt = %2d top = %2d hson = %2d tpos = %2d\n", fa, dep, scnt, top, hson, tpos);
    }
};

const int CHAIN_MAX = NS;
struct TreeChain{
    int val[CHAIN_MAX];
    int treeMaxNode;
    SegmentTree sTree;
    ForwardStart cTree;
    chainNode cNode[CHAIN_MAX];

    void buildTreeChain()
    {
        treeMaxNode = 0;
        dfsBase(1, -1, 1);
     //   printAll();
        dfsChain(1, -1, 1);
        sTree.build(1, 1, treeMaxNode);
   //     sTree.printAll();
    }

    void dfsBase(int rt, int fa, int dep)
    {
      //  printf("dfsBase:rt = %3d fa = %3d dep = %3d\n", rt, fa, dep);
        cNode[rt].init(fa, dep);

        int maxCnt = -1, hson = -1;
        for(int i = cTree.head[rt]; i != -1; i = cTree.edge[i].next)
        {
            int curson = cTree.edge[i].pst;
            if(curson == fa) continue;

            dfsBase(curson, rt, dep + 1);
            cNode[rt].scnt += cNode[curson].scnt;

            if(maxCnt < cNode[curson].scnt)
            {
                maxCnt = cNode[curson].scnt;
                hson = curson;
            }

        }
        cNode[rt].hson = hson;
    }

    void dfsChain(int rt, int fa, int top)
    {
     //   printf("dfsChain:rt = %3d fa = %3d top = %d\n", rt, fa, top);
        cNode[rt].top = top;
        cNode[rt].tpos = ++treeMaxNode;
        sTree.val[treeMaxNode] = val[rt];

        int hson = cNode[rt].hson;
        if(hson >= 0)
        {
            dfsChain(hson, rt, top);
        }

        for(int i = cTree.head[rt]; i != -1; i = cTree.edge[i].next)
        {
            int curson = cTree.edge[i].pst;
            if(curson == fa || hson == curson) continue;

            dfsChain(curson, rt, curson);
        }
    }

    void update(int u, int v, int value)
    {
     //   printf("##########tChain.update(%2d, %2d, %2d)", u, v, value);
        int topu = cNode[u].top;
        int topv = cNode[v].top;


        int l, r;
        if(topu == topv)
        {
            l = cNode[u].tpos;
            r = cNode[v].tpos;
            if(l > r) swap(l, r);
        //    printf(" a:l = %2d r = %2d\n", l, r);
            if(l <= 0)
            {
                printf("*****(1)树连剖分update异常:u = %d v = %d val = %d\n", u, v, value);
            //    return ;
            }
            sTree.update(1, l, r, 1, value);
        }
        else
        {
            int nextu = u;
            int nextv = v;

            int deptopu = cNode[topu].dep;
            int deptopv = cNode[topv].dep;
        //    printf(" topu = %2d(%2d) topv = %2d(%2d)", topu, deptopu, topv, deptopv);
            if(deptopu > deptopv)
            {
                l = cNode[topu].tpos;
                r = cNode[u].tpos;
                nextu = cNode[topu].fa;
            }
            else
            {
                l = cNode[topv].tpos;
                r = cNode[v].tpos;
                nextv = cNode[topv].fa;
            }
            sTree.update(1, l, r, 1, value);
            if(l <= 0)
            {
                printf("*****(2)树连剖分update异常:u = %d v = %d val = %d\n", u, v, value);
            //    return ;
            }
        //    printf(" b:l = %2d r = %2d\n", l, r);
            update(nextu, nextv, value);
        }
    }

    int query(int u, int v, int op)
    {
     //   printf("tChain.query(%2d, %2d, %2d)", u, v, op);
        int topu = cNode[u].top;
        int topv = cNode[v].top;

        int l, r;
        int ans;
        if(topu == topv)
        {
            l = cNode[u].tpos;
            r = cNode[v].tpos;
            if(l > r) swap(l, r);
            ans = sTree.query(1, l, r, op);
        //    printf(" l = %2d r = %2d\n", l, r, ans);
        }
        else
        {
            int nextu = u;
            int nextv = v;
            int deptopu = cNode[topu].dep;
            int deptopv = cNode[topv].dep;
            if(deptopu > deptopv)
            {
                l = cNode[topu].tpos;
                r = cNode[u].tpos;
                nextu = cNode[topu].fa;
            }
            else
            {
                l = cNode[topv].tpos;
                r = cNode[v].tpos;
                nextv = cNode[topv].fa;
            }
            ans = sTree.query(1, l, r, op);
          //  printf(" l = %2d r = %2d\n", l, r, ans);
            ans = max(ans, query(nextu, nextv, op));
        }
      //  printf(" query(%2d, %2d, %2d) = %d\n", u, v, op, ans);
        return ans;
    }

    void printNode(int rt)
    {
        printf("rt = %2d ", rt);
        cNode[rt].printData();
    }

    void printAll()
    {
        for(int i = 1; i < CHAIN_MAX; i++)
        {
            if(cNode[i].scnt > 0)
            {
                printNode(i);
            }
        }
    }
}tChain;

int main()
{

//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);

    while(~scanf("%d %d %d", &n, &m, &q))
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &tChain.val[i]);
        }

        tChain.cTree.init();
        int u, v;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d", &u, &v);
            tChain.cTree.addEdge(u, v, 1);
            tChain.cTree.addEdge(v, u, 1);
        }
      //  printf("input compelete!!!\n");
     //   tChain.cTree.printAll();

        tChain.buildTreeChain();

        int a,b,c;
        char ch[10];
        for(int i = 1; i <= q; i++)
        {
            scanf("%s", ch);
            if('I' == ch[0])
            {
                scanf("%d %d %d", &a, &b, &c);
                tChain.update(a, b, c);
            }
            else if('D' == ch[0])
            {
                scanf("%d %d %d", &a, &b, &c);
                tChain.update(a, b, -c);
            }
            else
            {
                scanf("%d", &a);
                int ans = tChain.query(a, a, 1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值