Bzoj1036 树链剖分基础题

树链剖分的基础题

因为复习到了这个部分突然发现竟然没有题解所以现在补一个。。

一些基础的东西。。。

重儿子:siz[u]为v的子节点中siz值最大的,那么u就是v的重儿子。

轻儿子:v的其它子节点。

重边:点v与其重儿子的连边。

轻边:点v与其轻儿子的连边。

重链:由重边连成的路径。

轻链:轻边。

然后简单的用两次dfs计算出每个节点的father,deep,size, son,w,top

其他简单的就不说了

w表示的是当前节点与其付清节点的连边在线段树中的位置

top表示的是当前节点所在的链的顶端的节点

其他的东西都比较简单,代码可以着重看下查询那段,因为不用求LCA所以不错。。。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define inf 0x7fffffff/4
#define MAX 123333
#define rep(i,j,k) for(int i=j;i<=k;i++)

using namespace std;

int n,m,father[MAX],deep[MAX],size[MAX],w[MAX],value[MAX],head[2*MAX];
int next[2*MAX],to[2*MAX],top[MAX],Max[MAX],sum[MAX];
int b[MAX],son[MAX],num=0,tot=0,done[MAX];
int l[4*MAX],r[4*MAX];

void add(int from,int To)
{
    to[++tot]=To;
    next[tot]=head[from];
    head[from]=tot;
}

void dfs(int fa,int x,int dep)
{
    deep[x]=dep;
    size[x]=1;
    son[x]=0;
    for(int i=head[x];i;i=next[i])
        if(to[i]!=fa)
        {
            father[to[i]]=x;
            dfs(x,to[i],dep+1);
            if(size[to[i]]>size[son[x]])
                son[x]=to[i];
            size[x]+=size[to[i]];
        }
}

void dfs2(int tp,int x)
{
    w[x]=++num;
    b[num]=value[x];
    top[x]=tp;
    if(son[x])
        dfs2(top[x],son[x]);
    for(int i=head[x];i;i=next[i])
        if(to[i]!=son[x]&&to[i]!=father[x])
            dfs2(to[i],to[i]);
}

inline void up(int x)
{
    if(l[x]==r[x])
        return;
    Max[x]=max(Max[2*x],Max[2*x+1]);
    sum[x]=sum[2*x]+sum[2*x+1];
}

inline void build(int x,int la,int ra)
{
    l[x]=la;
    r[x]=ra;
    if(la==ra)
    {
        Max[x]=sum[x]=b[la];
        return;
    }
    int mid=(la+ra)>>1;
    build(2*x,la,mid);
    build(2*x+1,mid+1,ra);
    up(x);
}

void change(int x,int pos,int number)
{
    if(l[x]==r[x]&&l[x]==pos)
    {
        Max[x]=sum[x]=number;
        return;
    }
    int mid=(l[x]+r[x])>>1;
    if(pos<=mid)
        change(2*x,pos,number);
    else
        change(2*x+1,pos,number);
    up(x);
}

int query_max(int x,int la,int ra)
{
    if(l[x]>ra||r[x]<la)
        return -inf;
    if(la<=l[x]&&r[x]<=ra)
        return Max[x];
    int mid=(l[x]+r[x])>>1;
    return max(query_max(2*x,la,ra),query_max(2*x+1,la,ra));
}

inline int ask_max(int x,int y)
{
    int ret=-inf;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])
            swap(x,y);
        ret=max(ret,query_max(1,w[top[x]],w[x]));
        x=father[top[x]];
    }
    if(w[x]<w[y])
        swap(x,y);
    ret=max(ret,query_max(1,w[y],w[x]));
    return ret;
}

int query(int x,int la,int ra)
{
    if(l[x]>ra||r[x]<la)
        return 0;
    if(la<=l[x]&&r[x]<=ra)
        return sum[x];
    return query(2*x,la,ra)+query(2*x+1,la,ra);
}

inline int ask(int x,int y)
{
    int ret=0;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])
            swap(x,y);
        ret+=query(1,w[top[x]],w[x]);
        x=father[top[x]];
    }
    if(w[x]<w[y])
        swap(x,y);
    return ret+query(1,w[y],w[x]);
}

int main()
{
    scanf("%d",&n);
    rep(i,1,n-1)
    {
        int a1,a2;
        scanf("%d%d",&a1,&a2);
        add(a1,a2),add(a2,a1);
    }
    rep(i,1,n)
        scanf("%d",&value[i]);
    dfs(0,1,1);
    memset(done,0,sizeof(done));
    dfs2(1,1);
    build(1,1,num);
    for(scanf("%d",&m);m;m--)
    {
        getchar();
        char ask_[90];
        int a1,a2;
        scanf("%s%d%d",ask_,&a1,&a2);
        if(ask_[0]==‘C‘)
            change(1,w[a1],a2);
        else
            if(ask_[1]==‘M‘)
                printf("%d\n",ask_max(a1,a2));
            else
                printf("%d\n",ask(a1,a2));
    }
    return 0;
}

Bzoj1036 树链剖分基础题,码迷,mamicode.com

时间: 2024-11-05 21:53:30

Bzoj1036 树链剖分基础题的相关文章

HDU 2966 Aragorn&#39;s Story 树链剖分第一题 基础题

Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, the enemy has N camps out of his kingdom and M edges c

HDU 3966 Aragorn&#39;s Story(树链剖分 模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, th

BZOJ 2243 染色 | 树链剖分模板题进阶版

BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上还是原树上,把两个区间的信息合并的时候,要注意中间相邻两个颜色是否相同. 这代码好长啊啊啊啊 幸好一次过了不然我估计永远也De不出来 #include <cstdio> #include <cstring> #include <algorithm> using namesp

bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入的第一行为一个整数n,表示节点的个数.接下来n – 1行,每行

【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题

题解:裸的,没什么好说的. 树链剖分不会的先理解一下重链轻链,然后直接扒我代码理解就行了. 贴代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 30100 #define inf 0x3f3f3f3f using namespace std; struct KSD { int u,v,next; }e[N<<1];

BZOJ 2243 染色(树链剖分好题)

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Status][Discuss] Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写一个程序依

SPOJ Query on a tree 树链剖分 水题

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to tior QUERY a b : ask fo

hdu 5029 Relief grain(树链剖分好题)

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 295    Accepted Submission(s): 66 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is fa

spoj Query on a tree(树链剖分模板题)

375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of