首页 > 其他分享 >HDU3966(树链剖分)

HDU3966(树链剖分)

时间:2023-05-31 17:33:30浏览次数:50  
标签:rt head 剖分 int void son edge HDU3966 树链


题目:Aragorn's Story

 

题意:给一棵树,并给定各个点权的值,然后有3种操作:

I C1 C2 K: 把C1与C2的路径上的所有点权值加上K

D C1 C2 K:把C1与C2的路径上的所有点权值减去K

Q C:查询节点编号为C的权值

 

分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可,注意HDU的OJ采用Windows系统,容易爆栈,所以在代码

前面加上:#pragma comment(linker, "/STACK:1024000000,1024000000")进行手动扩栈。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <vector>

using namespace std;
const int N=50010;

int n,m,Q;
int tim;

int num[N],siz[N],top[N],son[N];
int dep[N],tid[N],rank[N],fa[N];
int head[N],to[2*N],next[2*N],edge;

void Init()
{
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    tim=0;
    edge=0;
}

void addedge(int u,int v)
{
    to[edge]=v,next[edge]=head[u],head[u]=edge++;
    to[edge]=u,next[edge]=head[v],head[v]=edge++;
}

//树链剖分部分
void dfs1(int u,int father,int d)
{
    dep[u]=d;
    fa[u]=father;
    siz[u]=1;
    for(int i=head[u];~i;i=next[i])
    {
        int v=to[i];
        if(v!=father)
        {
            dfs1(v,u,d+1);
            siz[u]+=siz[v];
            if(son[u]==-1||siz[v]>siz[son[u]])
                son[u]=v;
        }
    }
}

void dfs2(int u,int tp)
{
    top[u]=tp;
    tid[u]=++tim;
    rank[tid[u]]=u;
    if(son[u]==-1) return;
    dfs2(son[u],tp);
    for(int i=head[u];~i;i=next[i])
    {
        int v=to[i];
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}

//线段树部分
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1

int sum[4*N],col[4*N];

void PushUP(int rt)
{
    sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}

void PushDown(int rt,int m)
{
    if(col[rt])
    {
        col[rt<<1]+=col[rt];
        col[rt<<1|1]+=col[rt];
        sum[rt<<1]+=(m-(m>>1))*col[rt];
        sum[rt<<1|1]+=(m>>1)*col[rt];
        col[rt]=0;
    }
}

void Build(int l,int r,int rt)
{
    col[rt]=0;
    if(l==r)
    {
        sum[rt]=num[rank[l]];
        return;
    }
    int mid=(l+r)>>1;
    Build(lson);
    Build(rson);
    PushUP(rt);
}

void Update(int L,int R,int v,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        col[rt]+=v;
        sum[rt]+=v*(r-l+1);
        return;
    }
    PushDown(rt,r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid)
        Update(L,R,v,lson);
    if(R>mid)
        Update(L,R,v,rson);
    PushUP(rt);
}

int Query(int l,int r,int rt,int val)
{
    if(l==r)
        return sum[rt];
    PushDown(rt,r-l+1);
    int mid=(l+r)>>1;
    int ret=0;
    if(val<=mid) ret=Query(lson,val);
    else         ret=Query(rson,val);
    PushUP(rt);
    return ret;
}

void Change(int x,int y,int val)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        Update(tid[top[x]],tid[x],val,1,n,1);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    Update(tid[x],tid[y],val,1,n,1);
}

int main()
{
    char oper[5];
    int a,b,c;
    while(~scanf("%d%d%d",&n,&m,&Q))
    {
        Init();
        for(int i=1;i<=n;i++)
           scanf("%d",&num[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        dfs1(1,0,0);
        dfs2(1,1);
        Build(1,n,1);
        while(Q--)
        {
            scanf("%s",oper);
            if(oper[0]=='Q')
            {
                scanf("%d",&a);
                printf("%d\n",Query(1,n,1,tid[a]));
            }
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                if(oper[0]=='D') c=-c;
                Change(a,b,c);
            }
        }
    }
    return 0;
}

 

标签:rt,head,剖分,int,void,son,edge,HDU3966,树链
From: https://blog.51cto.com/u_16146153/6388678

相关文章

  • 4543: [POI2014]Hotel加强版[树形DP+长链剖分]
    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4543 解题思路:长链剖分定义:f[i][j]表示以i为根节点的子树,有多少个节点和i的距离是j的.g[i][j]表示以i为根节点的子树,在子树外一个距离i为j的点可以跟i子树内的两个点组成两两相等的方案数.那么就有:f[u][j+1]+=f[v......
  • 树链剖分
    前言以下内容大多摘抄自董晓算法前置芝士相关定义重儿子:父节点的所有儿子中子树结点数目最多的结点轻儿子:父节点中除了重儿子之外的儿子重边:父结点和重儿子连成的边轻边:父结点和轻儿子连成的边重链:由多条重边连接而成的路径前置数组含义\(fa[u]\):存\(u\)的父节点\(......
  • 树链剖分
    我不会做ppt/ll先来看一棵树:树剖的经典问题:两种操作,一种是将点\(u\)到点\(v\)路径上所有点加上一个值;第二种是查询路径\(u\)到路径\(v\)的点权之和。显然,普通的树上差分已经无法解决这种问题了。于是我们需要一种预处理来降低复杂度。区间修改,这肯定用到线段树,但是......
  • Delaunay三角剖分——BW算法
    Delaunay三角剖分定义在数学和计算几何中,对于给定的平面中的离散点集P ,其Delaunay三角剖分DT()满足:空圆性:DT(P)是 唯一 的(任意四点不能共圆),在DT(P)中,任意 三角形的外接圆范围内不会有其它点存在。最大化最小角:在点集P 可能形成的三角剖分中,DT(P)所形成的三角形......
  • B. 染色(树链抛分)
    B.染色-树链剖分-比赛-衡中OI(tg.hszxoj.com)题目描述原题来自:SDOI2011给定一棵有  个节点的无根树和  个操作,操作共两类。将节点  到节点  路径上的所有节点都染上颜色;询问节点  到节点  路径上的颜色段数量,连续相同颜色的认为是同一段,例如 1......
  • hdu:How far away ?(树链剖分)
    ProblemDescriptionTherearenhousesinthevillageandsomebidirectionalroadsconnectingthem.Everydaypeolealwaysliketoasklikethis“HowfarisitifIwanttogofromhouseAtohouseB”?Usuallyithardtoanswer.Butluckilyintthisvilla......
  • 树链剖分学习笔记
    一棵树,支持:路径加单点查询一般树上链的问题使用树链剖分解决。重链剖分前置知识LCA,线段树定义重儿子:所有儿子中子树最大的儿子为重儿子重边:重儿子之间的连边重链:若干重儿子连成的链性质一棵树可以被剖成若干重链。优先遍历重儿子,所有重链的dfs序连续。重链数量不......
  • 最近公共祖先 树链剖分
    例题:洛谷P3379【模板】最近公共祖先(LCA)https://www.luogu.com.cn/problem/P3379首先是几个概念重儿子:父结点所有子树中最大的子树的根节点(只有一个或没有)轻儿子:父结点除了重儿子以外的所有子结点(没有或有很多个)重边:父结点和重儿子连的边轻边:父结点和轻儿子连的边重链:相接......
  • 【学习笔记】长链剖分
    简述在常规树链剖分中把重儿子设成\(siz\)最大的儿子,这样从根跳重链时子树大小至少减半,因此只需要\(O(\logn)\)次即可到达任何节点。考虑把关键字由\(siz\)改成子树内最大的深度\(dep\),这样的剖分方法称为长链剖分。voiddfs1(intu,intfa,intd){dep[u]=d,mxdep......
  • 长链剖分学习笔记
    一些定义重子节点表示其子节点中子树深度最大的子结点如果有多个子树最大的子结点,取其一。如果没有子节点,就无重子节点。轻子节点表示剩余的子结点从这个结点到重子节点的边为重边到其他轻子节点的边为轻边若干条首尾衔接的重边构成重链把落单的结点也当作重链,那么整棵......