首页 > 其他分享 >树链剖分笔记

树链剖分笔记

时间:2024-03-05 18:22:21浏览次数:22  
标签:剖分 int tree long 树链 dfn 笔记 now MX

树链剖分+线段树代码量通常在3K左右,出错的地方非常多,为了好好练手,特建立该题单,建议不要进行复制每一题都老老实实重打

题单 博客 题单Orz

1. 区间加,区间修改,区间最大值

#include<bits/stdc++.h>
using namespace std;const int MX=1e5+10;
int n,m,r,p;int input[MX]={0};int siz[MX]={0};int fath[MX]={0};int top[MX]={0};int dfn[MX]={0};int son[MX]={0};int high[MX]={0};int w[MX]={0};
//线段树好闪,拜谢线段树
struct node{
    long long sum;
    long long lc,rc;
    long long lazy;
}tree[MX<<1];
long long cnt=1,root=1;
inline void update(long long now){
    tree[now].sum=tree[tree[now].lc].sum+tree[tree[now].rc].sum;
}
inline void addnode(long long &now,long long l,long long r,long long val){
    if(now==0)  now=++cnt;
    tree[now].sum+=((r-l+1)*val)%p;tree[now].sum%=p;
    tree[now].lazy+=val%p;tree[now].lazy%=p;
}
inline void pushdown(long long now,long long l,long long r){
    if(l>=r)  return;
    long long mid=(r+l-1)>>1;
    addnode(tree[now].lc,l,mid,tree[now].lazy);
    addnode(tree[now].rc,mid+1,r,tree[now].lazy);
    tree[now].lazy=0;
}
void add(long long now,long long lt,long long rt,long long l,long long r,long long val){
    if(lt>r||l>rt)  return;
    if(l<=lt&&rt<=r){
        addnode(now,lt,rt,val);
        return ;
    }
    long long mid=(rt+lt-1)>>1;pushdown(now,lt,rt);
    add(tree[now].lc,lt,mid,l,r,val);add(tree[now].rc,mid+1,rt,l,r,val);
    update(now);
    return ;
}
long long cy(long long now,long long lt,long long rt,long long l,long long r){
    if(lt>r||l>rt)  return 0;
    if(l<=lt&&rt<=r){
        return tree[now].sum;
    }
    long long mid=(rt+lt-1)>>1;pushdown(now,lt,rt);
    return (cy(tree[now].lc,lt,mid,l,r)+cy(tree[now].rc,mid+1,rt,l,r))%p;
}
void build_t(){
    for(int i=1;i<=n;i++){
        add(root,1,n,i,i,w[i]);
    }
}
/*
int siz[MX]={0};    大小
int fa[MX]={0};     父亲
int top[MX]={0};    重链开始的地方
int dfn[MX]={0};    DFS序
int son[MX]={0};   重儿子
int high[MX]={0};  高度
int w[MX]={0};     时间戳权值
*/
vector<int> vec[MX];
void dfs1(int now,int fa){//确定  大小,父亲,高度,重儿子
    siz[now]=1,fath[now]=fa,high[now]=high[fa]+1;
    int maxn=-0x3f3f3f3f;
    for(auto to:vec[now]){
        if(to==fa)  continue;
        dfs1(to,now);
        siz[now]+=siz[to];
        if(maxn<siz[to]){
            maxn=siz[to];
            son[now]=to;
        }
    }
}
int tim=0;

//  now :当前节点
//  fa  :重链开头(并不是父节点)
void dfs2(int now,int fa){//确定重链开头,时间戳,dfs序
    dfn[now]=++tim;
    top[now]=fa;
    w[tim]=input[now];
    if(!son[now])  return;    //没有重儿子就是叶子节点
    dfs2(son[now],fa);//先走重儿子
    for(auto to:vec[now]){
        if(to==fath[now]||to==son[now])  continue;
        dfs2(to,to);//不在fa的重链上,所以to重链的开头是自己
    }
}

int main(){
    scanf("%d%d%d%d",&n,&m,&r,&p);
    for(int i=1;i<=n;i++){
        scanf("%d",&input[i]);
    }
    for(int i=1;i<n;i++){
        int x,y;scanf("%d%d",&x,&y);
        vec[x].push_back(y);vec[y].push_back(x);
    }
    dfs1(r,r);
    dfs2(r,r);
    build_t();
    for(int i=1;i<=m;i++){
        int op;scanf("%d",&op);
        if(op==1){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            z%=p;
            while(top[x]!=top[y]){
                if(high[top[x]]<high[top[y]]){
                    swap(x,y);
                }
                add(root,1,n,dfn[top[x]],dfn[x],z);
                x=fath[top[x]];
            }
            if(high[x]>high[y])  swap(x,y);
            add(root,1,n,dfn[x],dfn[y],z);
        }
        else if(op==2){
            int x,y;
            scanf("%d%d",&x,&y);
            int sum=0;
            while(top[x]!=top[y]){
                if(high[top[x]]<high[top[y]])  swap(x,y);
                sum=(sum+cy(root,1,n,dfn[top[x]],dfn[x]))%p;
                x=fath[top[x]];
            }
            if(high[x]>high[y])  swap(x,y);
            sum=(sum+cy(root,1,n,dfn[x],dfn[y]))%p;
            printf("%d\n",sum%p);
        }
        else if(op==3){
            int x,z;
            scanf("%d%d",&x,&z);
            add(root,1,n,dfn[x],dfn[x]+siz[x]-1,z);
        }
        else{
            int x;
            scanf("%d",&x);
            printf("%d\n",cy(root,1,n,dfn[x],dfn[x]+siz[x]-1));
        }
    }

    return 0;
}

每次都直接重新打,在你吐之前一定能够熟练掌握这个算法!!

标签:剖分,int,tree,long,树链,dfn,笔记,now,MX
From: https://www.cnblogs.com/DaiFu/p/18054619

相关文章

  • JAVA私有构造函数---java笔记
    在Java中,构造函数是一种特殊的方法,它用于初始化新创建的对象。当我们创建一个类的实例时,构造函数会自动被调用。构造函数可以有不同的访问修饰符,如public、protected、default(即包级私有)和private。其中,private构造函数是Java中一种特殊的构造函数。私有构造函数(PrivateConstru......
  • Vue学习笔记33-生命周期
    示例一: <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>引入生命周期</title>......
  • GDB调试入门笔记
    目录What?WhyHow安装GDB安装命令查看是否安装成功调试简单的程序预备一个程序调试使用breakinfolistnextprintstepWhat?GDB是什么?全称GNUsymbolicdebugger百度百科的解释:程序调试工具UNIX及UNIX-like下的调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试......
  • 学习笔记:AutoSTG
    AutoSTG:NeuralArchitectureSearchforPredictionsofSpatio-TemporalGraph期刊会议:WWW2021论文地址:https://dl.acm.org/doi/10.1145/3442381.3449816代码地址:https://github.com/panzheyi/AutoSTG总结AutoSTG不仅自学网络权重,还自学网络结构。网络结构的学习采用Dar......
  • 《Document-level Relation Extraction as Semantic Segmentation》论文阅读笔记
    原文代码摘要本文研究的是文档级关系抽取,即从文档中抽取出多个实体之间的关系。现有的方法主要是基于图或基于Transformer的模型,它们只考虑实体自身的信息,而忽略了关系三元组之间的全局信息。为了解决这个问题,本文提出了一种新的方法,它通过预测一个实体级关系矩阵来同时捕获局......
  • Vue学习笔记32--自定义指令--对象式
    Vue学习笔记32--自定义指令--对象式总结:1.autofocus属性,用于input自动获取焦点2.directives指令中this是指window3.vm中使用directives进行自定义指令,为局部指令4.全局指令和全局过滤器类似,应在vm之外使用directive进行声明使用自定义指令总结: 定......
  • Mac pro M3 笔记本 三指触控翻译失效
    1.问题:MacproM3笔记本三指触控翻译失效。期望功能效果如下:   2.设置    ......
  • 学习笔记:ST-MetaNet
    UrbanTrafficPredictionfromSpatio-TemporalDataUsingDeepMetaLearning使用深度元学习进行城市交通预测期刊会议:KDD2019论文地址:https://dl.acm.org/doi/10.1145/3292500.3330884代码地址:(mxnet)https://github.com/panzheyi/ST-MetaNet总结感觉这篇论文的元学......
  • Java学习笔记——第六天
    案例练习案例一:买飞机票需求用户购买机票时,机票原价会按照是淡季还是旺季,是头等舱还是经济舱的情况进行相应的优惠,优惠方案如下:5-10月为旺季,头等舱9折,经济舱8.5折;11月到来年4月为淡季,头等舱7折,经济舱6.5折,请开发程序计算出用户当前机票的优惠价。分析方法是否需要接收数据?......
  • JAVA学习笔记--运算符
    运算符注意:()的优先级最高,因此可以多打一些()提高代码的可读性!!算术运算符:+、-、*、/、%(模:取余)、++(自增)、--(自减)publicclassDemo1{publicstaticvoidmain(String[]args){inta=10;intb=20;System.out.println(a+b);......