LOJ #10134. 「一本通 4.4 练习 1」Dis

news2024/10/6 22:30:49


分析

根据数据范围分析一下复杂度,Floyd和dj算法都必爆。

发现题目说的是树,还是边还是双向的(树本身就是无向的,连通无回路的无向图叫做无向树,简称树。如果题目说了树,那么默认边就是双向的),也没指明根节点,那么就是无根树,任选一个节点当根节点。

思路

是树的话就简单了,任意两点之间的最短距离很容易想到最近公共祖先,x到LCA的距离加上y到LCA的距离就是最短距离。

考虑在LCA预处理的dfs里面加上dis数组维护每个节点到根节点的距离。

那么x,y两点的最短距离就是dis[x]+dis[y]-2*dis[lca(x,y)]

AC代码

#include <bits/stdc++.h>
using namespace std;

inline int read(){
    int x=0;char c=getchar();
    while(c<48 or c>57)c=getchar();
    while(c>=48 and c<=57)x=(x<<3)+(x<<1)+(c xor 48),c=getchar();
    return x;
}

using pii=pair<int,int>;
const int N=1e4+5;
int n,m,lg[N],d[N],f[N][15],dis[N];
vector<pii>e[N];
bitset<N>vis;

void dfs(int now,int fa){
    if(vis[now])return;//使用vector别忘了加vis,不然会访问父节点
    vis[now]=true;
    f[now][0]=fa;
    d[now]=d[fa]+1;
    for(int i=1;i<=lg[d[now]];++i)
        f[now][i]=f[f[now][i-1]][i-1];
    for(auto i:e[now]){
        if(!vis[i.second]){
            dis[i.second]=dis[now]+i.first;
            dfs(i.second,now);
        }
    }
}
int lca(int x,int y){
    if(d[x]<d[y])swap(x,y);
    while(d[x]>d[y])x=f[x][lg[d[x]-d[y]]-1];
    if(x==y)return x;
    for(int i=lg[d[x]];i>=0;--i)
        if(f[x][i]!=f[y][i]){
            x=f[x][i];
            y=f[y][i];
        }
    return f[x][0];
}

int main(){
    ios::sync_with_stdio(false);
    n=read(),m=read();
    for(int i=1,x,y,k;i<=n-1;++i){
        x=read(),y=read(),k=read();
        e[x].push_back({k,y});
        e[y].push_back({k,x});
    }

    for(int i=1;i<=n;++i)
        lg[i]=log(i)/log(2)+1;
    dfs(1,1);

    for(int i=1,x,y;i<=m;++i){
        x=read(),y=read();
        cout<<dis[x]+dis[y]-2*dis[lca(x,y)]<<endl;
    }
    return 0;
}

倍增LCA代码细节有点多,被卡了两发。

1. d[x]>d[y]跳到同一深度之后先判断是不是到一个点了,是就直接返回。

2. 往上跳的时候是f[x][lg[d[x]-d[y]]-1],因为预处理的时候lg加了1

另外还有一道升级版#2491. 「BJOI2018」求和 - 题目 - LibreOJ (loj.ac)

在洛谷也有收录P4427 [BJOI2018] 求和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

做一题水两边真是太好啦qwq


前一题只需要开一个数组dis来维护,这里k的范围有50,所以要开dis[N][51],来预处理所有深度的k次方,因为要取模所以会用到快速幂,注意根节点1的深度是0,特判返回值。

因为模数比较大别忘了开long long。

快速幂

int qkpow(int a,int k){
    int res=1;
    if(a==0)return 0;//特判0
    while(k){
        if(k&1)res*=a;
        k>>=1;
        a*=a;
        a%=MOD;
        res%=MOD;
    }
    return res;
}

预处理

    //预处理深度i^k次
    for(int i=0;i<N;++i){
        for(int k=1;k<=50;++k){
            a[i][k]= qkpow(i,k);
        }
    }

    d[1]=-1;//这里为-1和我的dfs用法有关
    for(int i=1;i<=n;++i)
        lg[i]=log(i)/log(2)+1;

大法师

void dfs(int now,int fa){
    if(vis[now])return;
    vis[now]=true;
    d[now]=d[fa]+1;
    for(int j=1;j<=50;++j){
        p[now][j]=p[fa][j]+a[d[now]][j];//子节点的j次方前缀和
        p[now][j]%=MOD;
    }
    f[now][0]=fa;
    for(int i=1;i<=lg[d[now]];++i)
        f[now][i]=f[f[now][i-1]][i-1];
    for(auto i:e[now]){
        dfs(i,now);
    }
}

LCA函数部分是一样的就不搬过来了。

这道题是点的前缀和,和前一题边的前缀和不一样。

边和只要减去两倍的LCA就行了,但是点和我们要算上LCA的值,所以是减去LCA和LCA的父节点。

注意

因为最终答案涉及了取模中减法,相减之后可能答案为负数,需要加上MOD再模上MOD。

如果取模中有除法不可轻易使用取模(基本必错),需要使用乘法逆元来计算。

如果递推式使用的是除法并且不会逆元,考虑用加法和减法去递推。

AC代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

inline int read(){
    int x=0;char c=getchar();
    while(c<48 or c>57)c=getchar();
    while(c>=48 and c<=57)x=(x<<3)+(x<<1)+(c xor 48),c=getchar();
    return x;
}

const int N=3e5+5,MOD=998244353;
int n,m,d[N],f[N][20],lg[N],a[N][51],p[N][51];
vector<int>e[N];
bitset<N>vis;

int qkpow(int a,int k){
    int res=1;
    if(a==0)return 0;//特判0
    while(k){
        if(k&1)res*=a;
        k>>=1;
        a*=a;
        a%=MOD;
        res%=MOD;
    }
    return res;
}
void dfs(int now,int fa){
    if(vis[now])return;
    vis[now]=true;
    d[now]=d[fa]+1;
    for(int j=1;j<=50;++j){
        p[now][j]=p[fa][j]+a[d[now]][j];//子节点的j次方前缀和
        p[now][j]%=MOD;
    }
    f[now][0]=fa;
    for(int i=1;i<=lg[d[now]];++i)
        f[now][i]=f[f[now][i-1]][i-1];
    for(auto i:e[now]){
        dfs(i,now);
    }
}
int lca(int x,int y){
    if(d[x]<d[y])swap(x,y);
    while(d[x]>d[y])x=f[x][lg[d[x]-d[y]]-1];
    if(x==y)return x;
    for(int i=lg[d[x]];i>=0;--i)
        if(f[x][i]!=f[y][i]){
            x=f[x][i];
            y=f[y][i];
        }
    return f[x][0];
}

signed main(){
    ios::sync_with_stdio(false);
    n=read();
    for(int i=1,x,y;i<=n-1;++i){
        x=read(),y=read();
        e[x].push_back(y);
        e[y].push_back(x);
    }

    //预处理深度i^k次
    for(int i=0;i<N;++i){
        for(int k=1;k<=50;++k){
            a[i][k]= qkpow(i,k);
        }
    }

    d[1]=-1;
    for(int i=1;i<=n;++i)
        lg[i]=log(i)/log(2)+1;
    dfs(1,1);

    m=read();
    for(int i=1,x,y,k,LCA;i<=m;++i){
        x=read(),y=read(),k=read();
        LCA=lca(x,y);
        cout<<((p[x][k]+p[y][k]-p[LCA][k]-p[f[LCA][0]][k])%MOD+MOD)%MOD<<endl;
        //警惕模运算带来的坑
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1233237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

腾讯云服务器标准型S5实例CPU性能如何?配置特性说明

腾讯云服务器CVM标准型S5实例具有稳定的计算性能&#xff0c;CVM 2核2G S5活动优惠价格280.8元一年自带1M带宽&#xff0c;15个月313.2元、2核4G配置748.2元15个月&#xff0c;CPU内存配置还可以选择4核8G、8核16G等配置&#xff0c;公网带宽可选1M、3M、5M或10M&#xff0c;腾…

uniapp和vue3+ts创建自定义下拉选择框组件

使用uniapp开发小程序的时候&#xff0c;使用了uview的ui组件&#xff0c;但是里面没有下拉选择组件&#xff0c;只有Picker 选择器&#xff0c;但是我们想要使用下拉选择的组件&#xff0c;所以需要自定义个一个下拉选择的自定义组件&#xff0c;我就只能自己动手创建这个自定…

公网环境固定域名异地远程访问内网BUG管理系统

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…

【OpenGauss源码学习 —— 列存储(ColumnTableSample)】

执行算子&#xff08;ColumnTableSample&#xff09; 概述ColumnTableSample 类ColumnTableSample::ColumnTableSample 构造函数ColumnTableSample::~ColumnTableSample 析构函数ExecCStoreScan 函数ColumnTableSample::scanVecSample 函数ColumnTableSample::getMaxOffset 函数…

前端实现移动端Tab栏(附带源码)

文章目录 先上图,附带源码index.html 主要视图层Main.css 主要样式demo.css主要的JS,在index.html 引入即可先上图,附带源码 提示:一款JS和CSS3炫酷Tabbar导航栏动画特效。该Tabbar导航栏在点击切换时,会有类似波浪运动的动画效果,非常炫酷。 index.html 主要视图层 &l…

Hadoop-- hdfs

1、HDFS中的三个进程&#xff1a;NameNode&#xff08;NN&#xff09;、DataNode(DN)、SecondNameNode(SNN) 2、NameNode&#xff08;NN&#xff09; 1、作用&#xff1a; 1、接收客户端的一个读、写的服务&#xff0c;在namenode上存储了数据文件和datanode的映射的关系。 …

Python实现WOA智能鲸鱼优化算法优化随机森林回归模型(RandomForestRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 鲸鱼优化算法 (whale optimization algorithm,WOA)是 2016 年由澳大利亚格里菲斯大学的Mirjalili 等提…

[C语言 数据结构] 栈

1.什么是栈&#xff1f; 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压…

Java高级编程-----网络编程

网络通信协议 通过计算机网络可以实现多台计算机连接&#xff0c;但是不同计算机的操作系统和硬件体系结构不同&#xff0c;为了提供通信支持&#xff0c;位于同一个网络中的计算机在进行连接和通信时必须要遵守一定的规则&#xff0c;这就好比在道路中行驶的汽车一定要遵守交…

C++ LibCurl实现Web隐藏目录扫描

LibCurl是一个开源的免费的多协议数据传输开源库&#xff0c;该框架具备跨平台性&#xff0c;开源免费&#xff0c;并提供了包括HTTP、FTP、SMTP、POP3等协议的功能&#xff0c;使用libcurl可以方便地进行网络数据传输操作&#xff0c;如发送HTTP请求、下载文件、发送电子邮件等…

Android AIDL中使用Surface问题

1.构建ITest.aidl文件 package com.xxx.xxxx;import android.view.Surface;interface IMonitorService {boolean addSurface(in Surface surface);boolean removeSurface(in Surface surface); } 2.构建时报错 3.Surface源码分析 android.view.Surface中包含两个Surface类&am…

泛型进阶:通配符

基本概念 对泛型不了解的可以看这篇博客&#xff1a;数据结构前瞻-CSDN博客 一般来说&#xff0c;&#xff1f;在泛型里的使用就是通配符 看看下面的代码 class Message<T> {private T message ;public T getMessage() {return message;}public void setMessage(T m…

新生儿斜视:原因、科普和注意事项

引言&#xff1a; 新生儿斜视是一种儿童眼部常见的问题&#xff0c;指的是眼球的定位不正常&#xff0c;造成双眼无法同时注视同一个物体。了解新生儿斜视的原因、科普相关知识&#xff0c;并提供适当的注意事项&#xff0c;对于早期发现和处理这一问题至关重要。本文将深入探…

通过css设置元素隐藏和显示

背景&#xff1a;鼠标悬浮时显示删除&#xff0c;放开后显示组件名 解决&#xff1a;通过display:none和display:block显示和隐藏元素&#xff1b; 使用 div p选择器选择当前div的下一个紧跟的p元素 <div v-if"!preview" class"name">{{propertyDa…

企业办公室信息安全保密办法——推荐用天锐绿盾数据安全防泄密系统 | 防止核心文件数据、资料泄露

天锐绿盾数据安全防泄密系统是一种有效的办公室信息安全保密办法。该系统采用驱动层透明加密技术&#xff0c;对电子文件进行自动加密&#xff0c;保护数据的安全性和隐私性。 PC端访问地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c…

配置Java环境变量不生效的解决办法

问题&#xff1a; 直接更换Java_HOME的JDK安装路径后&#xff0c;竟然环境变量不生效&#xff0c;在cmd窗口输入java -version或者javac -version后报错&#xff1f;&#xff1f;&#xff1f;这是为什么呢&#xff1f; 问题剖析&#xff1a; 在使用安装版本的JDK程序时&#…

论文阅读:“基于快速特征点提取和描述算法与色调、饱和度和明度的图像特征点匹配算法”

文章目录 摘要引言方法实验结果图像预处理结果对比图像配准结果对比 参考文献 摘要 提出了一种基于快速点特征提取和描述&#xff08;ORB&#xff09;算法与色调、饱和度和明度&#xff08;HSV&#xff09;的图像特征点匹配算法。首先利用双边滤波和均值滤波结合对图像进行预处…

深度剖析倍增算法求解最近公共祖先(LCA)的细枝末节

1. LCA&#xff08;最近公共祖先&#xff09; 倍增算法的基本思想在前面的博文中有较详细的介绍&#xff0c;本文不再复述。此文仅讲解如何使用倍增算法求解多叉树中节点之间的最近公共祖先问题。 什么是最近公共祖先问题&#xff1f; 字面而言&#xff0c;指在树上查询两个…

C++入门第八篇---STL模板---list的模拟实现

前言&#xff1a; 有了前面的string和vector两个模板的基础&#xff0c;我们接下来就来模拟实现一下list链表模板&#xff0c;我还是要强调的一点是&#xff0c;我们模拟实现模板的目的是熟练的去使用以及去学习一些对于我们本身学习C有用的知识和用法&#xff0c;而不是单纯的…

35+大龄程序员从焦虑到收入飙升:我的搞钱副业套路分享

37岁大龄程序员&#xff0c;一度觉得自己的职场生涯到头了。既没有晋升和加薪的机会&#xff0c;外面的公司要么接不住我的薪资&#xff0c;要么就是卷得不行&#xff0c;无法兼顾工作和家庭&#xff0c;感觉陷入了死局…… 好在我又重新振作起来&#xff0c;决定用副业和兼职…