首页 > 其他分享 >树上点差分的经典应用 LuoguP3258松鼠的新家

树上点差分的经典应用 LuoguP3258松鼠的新家

时间:2024-04-17 14:55:57浏览次数:13  
标签:ch 新家 log int LuoguP3258 number 差分 --

树上点差分的核心就是如何避免重复,即正确的运用差分数组
例如a,b点路径上点权值加1,则把a,b路径找到,并找到其LCA,此时可以把a到根,b到根这两条路径看出两条链,把每条链看出我们熟悉的
顺序差分结构.以其中一条链为例子,把a当成数组的起点,根当成数组的末尾,进行差分,显然有C[a]++,C[f[lca][0]]--(这里f[lca][0]为lca的父节点)
附上图片理解(摘自Oi-wiki)

故对a到b的路径上的差分修改的完整过程为C[a]++,C[b]++,C[lca]--(因为加了两次,要减去1次),C[f[lca][0]]--;
最后附上这条代码(里面还有一些具体应用的细节)

点击查看代码
//本题有点特殊,因为同时作为路径起点与终点的点差分值多算了一次,但仅限于点差分!!!
#include <bits/stdc++.h>
using namespace std;
typedef struct edge//链式前向星
{
    int to,next;
}EDGE;
EDGE e[600005];//边
int head[300001];//以i为起点的第一条边
int cnt;//边的数量
int number[300001];//答案,同时兼具差分功能
int a[300001];//访问顺序
int f[300001][30];//倍增父节点
int depth[300001];//深度,服务于倍增
inline int read()//快读
{
    int s = 0;
    char ch = getchar();
    while(ch > '9'||ch < '0') ch = getchar();
    while(ch >= '0'&&ch <= '9')
    {
        s = s*10 + ch - '0';
        ch = getchar();
    }
    return s;
}
void add(int x,int y)//加边
{
    e[++cnt].to = y;
    e[cnt].next = head[x];
    head[x] = cnt;
}
void DFS(int x,int fa)//建树及预处理LCA
{
    depth[x] = depth[fa] + 1;//深度加1
    f[x][0] = fa;//第一个父节点
    for (int i = 1;(1<<i)<=depth[x];i++)//倍增父节点
    {
        f[x][i] = f[f[x][i-1]][i-1];
    }
    for (int i = head[x];i;i = e[i].next)//遍历子树
    {
        if(e[i].to == fa) continue;
        DFS(e[i].to,x);
    }
}
void LCA(int a,int b)//求LCA兼具差分
{
    if(depth[a]<depth[b]) swap(a,b);//不妨a的深度大于b
    number[a]++;//差分思想
    number[b]++;//差分思想
    while(depth[a]>depth[b])//向上跳至深度相同
    {
        a = f[a][(int)(log(depth[a]-depth[b])/log(2))];//以后尽量不用用log写法,容易出错且不美观
    }
    if(a == b)
    {
        number[a]--;//祖先减1
        number[f[a][0]]--;//祖先的父亲减1,这样保证了LCA只减了1
        return;一定要返回
    }
    for (int i = (int)(log(depth[a])/log(2));i>=0;i--)//以后尽量不用用log写法,容易出错且不美观
    {
        if(f[a][i] != f[b][i])
        {
            a = f[a][i];
            b = f[b][i];
        }
    }
    number[f[a][0]]--;//同上原理
    number[f[f[a][0]][0]]--;
}
void Solve(int x,int fa)//计算子树和
{
    for (int i = head[x];i;i = e[i].next)
    {
        if(e[i].to == fa) continue;
        Solve(e[i].to,x);
        number[x] += number[e[i].to];//及求区间和,差分思想
    }
}
int main()
{
    int n = read();//读入节点数
    for (int i = 1;i<=n;i++)//读入访问顺序    
    {
        a[i] = read();
    }
    for (int i = 1;i<=n-1;i++)//建树
    {
        int x = read();
        int y = read();
        add(x,y);
        add(y,x);
    }
    depth[0] = -1;
    DFS(1,0);//预处理
    for (int i = 1;i<=n-1;i++)//求LCA及差分
    {
        LCA(a[i],a[i+1]);
    }
    Solve(1,0);//计算子树和,计算区间和(注意这里是先计算区间和,再对多加点进行减法操作)
    for (int i = 2;i<=n;i++) number[a[i]]--;//同时为起点终点的多加了一次,要减1,同时最后一点为餐厅,不用糖果,减1
    for (int i = 1;i<=n;i++)//输出
    {
        printf("%d\n",number[i]);
    }
    return 0;
}
码字不易,多多支持!!

标签:ch,新家,log,int,LuoguP3258,number,差分,--
From: https://www.cnblogs.com/cuijunjie18/p/18140728

相关文章

  • 振弦采集仪在岩土工程监测中的误差分析与校正方法
    振弦采集仪在岩土工程监测中的误差分析与校正方法河北稳控科技振弦采集仪是岩土工程监测中常用的一种测量设备,用于测量岩土体的动力特性,如波速、阻尼等参数。然而,由于各种因素的影响,振弦采集仪在实际应用中存在一定的误差,因此需要进行误差分析和校正。本文将就振弦采集仪的误差分......
  • 2024最新家庭版升级专业版密钥
    Windows11专业版是面向小型企业和组织的Windows11版本。它包含了家庭版的所有功能,并增加了一些额外的功能,例如:设备加密:使用BitLocker对设备上的驱动器进行加密,以保护敏感数据。远程桌面:从任何位置远程连接到您的设备。多用户登录:允许多个用户同时使用您的设备,每个用户......
  • 差分约束应用题
    //差分约束,此题难点在于如何找出这些关系//1-24是一个环,这里处理办法是把24时固定//当i>8时,s[i]>=R[i]+s[i−8]//当i<=7时,s[i]>=s[16+i]-s[24]+R[i]//当1<=i<=24时,s[i]>=s[i−1],s[i-1]>=s[i]-num[i]#include<iostream>#inclu......
  • [学习笔记] 树上差分 - 图论
    前置知识:树,LCA,前缀和与差分边差分这个名字是在网上看到的,不理解为什么要叫这么一个名字,可能是因为它与树链修改有关。当然,用于树链修改单点查询非常方便~看这个图,该图是以点1为根进行DFS的。如果我们要把从3->4这条树链上所有的点统统加上1,可以都转化为对到根节点的......
  • 简单处理——FPGA实现图像中心差分变换
    简单处理——FPGA实现图像中心差分变换一、图像中心差分变换算法简介​ 差分图像就是目标场景在连续时间内图像相减所构成的图像,对图像进行中心差分变换的主要目的是计算图像中心每个像素点的梯度,而每个像素点的梯度在图像处理中就可以被用于描述图像中灰度变化的快慢和方向。......
  • 关于差分约束的一切
    观前须知笔者的博客主页声明本文使用CCBY-NC-SA4.0许可。本文为笔者在OI学习中的复习向学习笔记。部分内容会比较简略。如有好的习题会不断补充。知识简介差分约束解决这样一类问题:给定一个n元一次不等式组,让你求出一组解/判定是否有解/算出某个数的最值/算出和......
  • 【蓝桥·算法双周赛 第 9 场 小白入门赛】字符迁移【算法赛】题解(字符串+模运算+差分)
    思路差分数组是一种特殊的数组,它的第iii个数定义为原数组的第ii......
  • 简单处理——二值化(钢笔画)和差分化(浮雕画)
    简单处理——二值化(钢笔画)和差分化(浮雕画)一、钢笔画和浮雕画​ RGB转灰度图就类似于英语学习中的abandon,在熟悉了YCbCr等颜色空间以及简单的图像反转之后,我们可以将目光移向今天的主题——二值化和差分化;​ 二值化概念比较简单,就是你给灰度在0—255的灰度图像设置一个阈值,大于......
  • 差分和前缀和——蓝桥杯备赛
    一、大学里的树木要打药问题描述教室外有N棵树,根据不同的位置和树种,学校要对其上不同的药。因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。树的编号从0∼N−1且N<1e6。对于树的药是成区间分布,比如3∼5号的树靠近下水道,所以他们要用驱蚊虫的药,20......
  • 差分
    前言学习差分前一定要先学习前缀和,因为差分就是前缀和的一个逆运算(有点像微分和积分),所以只有先搞清楚前缀和才能明白差分点这里补习前缀和这里同样也是从一维和二维两个角度去分析差分这个算法正文我们要先理清差分的含义:注意关系,这里跟前缀和里举的例子有差别,b的前缀和数组......