首页 > 其他分享 >树上可修改式背包

树上可修改式背包

时间:2024-11-29 14:04:38浏览次数:7  
标签:10 背包 fa int long 修改 ai 树上 dp

树上可修改式背包

题目描述

给出一棵 n n n 个点以 1 1 1 为根的有根树,第 i i i 个点的父亲为 f i f_i fi​ ,每个点上有点权 a i a_i ai​ 。

你需要维护 m m m 次操作,操作分为两种:

  • 格式为 1   x   y 1\ x\ y 1 x y ,表示令 a x ⟵ y a_x\longleftarrow y ax​⟵y。

  • 格式为 2   x   y 2\ x\ y 2 x y ,查询在点 x x x 的邻居中选出一个集合 S S S ,满足 ∑ i ∈ S a i = y \displaystyle\sum_{i\in S}a_i=y i∈S∑​ai​=y 的方案数对 998244353 998244353 998244353 取余的结果。

对于 100 % 100\% 100% 的数据, 1 ≤ n , q , a i , y ≤ 4 × 1 0 3 1\le n,q,a_i,y\le4\times10^3 1≤n,q,ai​,y≤4×103, 1 ≤ x ≤ n 1\le x\le n 1≤x≤n 。

输入格式

第一行两个整数 n , q n,q n,q ,表示点数和操作次数。

第二行 n − 1 n-1 n−1 个整数,第 i i i 个为 f i f_i fi​ 。

第三行 n n n 个整数,第 i i i 个为 a i a_i ai​ 。

接下来 q q q 行描述了 q q q 次操作。

输出格式

对于操作 2 2 2 每行一个整数。

样例输入 1 1 1

4 3
1 1 1
1 2 2 2
2 1 6
1 2 3
2 1 5

样例输出 1 1 1

1
2

首先有个朴素的思路:对于每次询问,求一个背包。

但毫无疑问的是,会超时。

与普通的背包不同的是,这题对于每个点是可以修改的,我们考虑怎么快速完成这个修改。

令 d p i , j dp_{i,j} dpi,j​ 表示点 i i i 的所有儿子中部分的和为 j j j 的方案数,可以先将 d p f a i , j dp_{fa_i,j} dpfai​,j​ 中除去 a i a_i ai​ ,然后将 a i a_i ai​ 改为 y y y ,再将 a i a_i ai​ 添回 d p f a i , j dp_{fa_i,j} dpfai​,j​ 中。注意我们再背包中添加时是倒序的(为了避免重复),我们再删时,为了避免减多,需要正序减。

void add(int x,int y){
    for(int i=N;i>=y;i--) update(dp[x][i],dp[x][i-y],1);
}
void del(int x,int y){
    for(int i=y;i<=N;i++) update(dp[x][i],dp[x][i-y],0);
}

而询问时,由于 d p i , j dp_{i,j} dpi,j​ 只考虑了点 i i i 的儿子,故我们可以将 a f a i a_{fa_i} afai​​ 添入 d p i , j dp_{i,j} dpi,j​ 中,输出完后再删去即可。

Code:

#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
const int N=4000;
int a[N+10],fa[N+10];
long long dp[N+10][N+10];
int n,q;
void update(long long&x,long long y,int f){
    if(f) x+=y;
    else x-=y;
    if(x>=mod) x-=mod;
    if(x<0) x+=mod;
}
void add(int x,int y){
    for(int i=N;i>=y;i--) update(dp[x][i],dp[x][i-y],1);
}
void del(int x,int y){
    for(int i=y;i<=N;i++) update(dp[x][i],dp[x][i-y],0);
}
int main(){
    scanf("%d%d",&n,&q);
    a[0]=N+10;
    for(int i=2;i<=n;i++) scanf("%d",&fa[i]);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        dp[i][0]=1;
    }
    for(int i=2;i<=n;i++) add(fa[i],a[i]);
    while(q--){
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1){
            del(fa[x],a[x]);
            a[x]=y;
            add(fa[x],a[x]);
        }
        else{
            add(x,a[fa[x]]);
            printf("%lld\n",dp[x][y]);
            del(x,a[fa[x]]);
        }
    }
    return 0;
}

标签:10,背包,fa,int,long,修改,ai,树上,dp
From: https://blog.csdn.net/axibaxhf/article/details/144028479

相关文章

  • React编译之后如何修改input控件的值
    问题: 因为React是通过setState方法改变值来影响页面展示的,所以直接修改页面值,并不能让React意识到state已经变化了。 修改自chatgpt4o提供的方法,20241129测试有效。 //第一个参数为原生组件,第二个参数为新值functionsetReactInputValue(input,value){constl......
  • 修改 PbootCMS 的邮件提醒标题
    PbootCMS提供了留言版和自定义表单的自动发送邮件提醒功能,非常方便。然而,默认的邮件标题会带有“【PbootCMS】”标识,这在为客户定制的网站中可能会带来一些不必要的麻烦。因此,我们可以对邮件标题进行优化,去掉或修改这个标识。修改步骤文件1:apps/admin/controller/system/Conf......
  • Client Hints 指纹修改
    ClientHints|BrowserScan一、ClientHints指纹介绍客户端提示是一组HTTP标头和一个JavaScriptAPI,允许Web浏览器将有关客户端设备和浏览器的详细信息发送到Web服务器。它们旨在成为User-Agent的继任者,并为Web服务器提供了一种标准化方法,以便为客户端优化内容,......
  • 屏幕分辨率|尺寸|颜色深度指纹修改
    一、前端通过window.screen接口获取屏幕分辨率尺寸颜色深度,横屏竖屏信息。 二、window.screenc++接口实现:1、third_party\blink\renderer\core\frame\screen.idl//https://drafts.csswg.org/cssom-view/#the-screen-interface[Exposed=Window]interfaceScre......
  • 屏幕触控支持指纹修改
    一、前端navigator.maxTouchPoints获取屏幕是否支持触控。二、navigator.maxTouchPointsc++接口修改。1、third_party\blink\renderer\core\events\navigator_events.idl//https://w3c.github.io/pointerevents/#extensions-to-the-navigator-interface[Implement......
  • django中admin模块中修改密码的form
    django中admin模块中修改密码的form,参考这个文件在E:\django5env\Lib\site-packages\django\contrib\auth\forms.py,其中写了好几个关于form的,可以参考其验证、错误信息等方法classPasswordChangeForm(SetPasswordForm):"""Aformthatletsauserchangetheirp......
  • docker修改存储路径
    停止Docker服务:sudosystemctlstopdocker复制现有的Docker存储目录到新位置(如果已有数据,确保已备份):sudorsync-aP/var/lib/docker//new/path/docker/修改Docker的服务文件。Docker的服务文件通常在/lib/systemd/system/docker.service。使用编辑器打开并修改ExecStar......
  • 林史·树上的男爵 2 | 5
    9话说涛哥日复一日地练习打猎,打猎技术早就有了提升,也使得涛哥的一日三餐日益丰盛起来但是有一个问题始终困扰着涛哥,如果涛哥不下树的话,意味着很多猎物涛哥是没有办法捡到的。在树上打猎的限制很多,通常来讲涛哥只能打天上飞的猎物,并且猎物还要恰好停在树上,否则就会掉到地上去,让涛......
  • Elasticearch索引mapping写入、查看、修改
    作者:京东物流陈晓娟一、ESElasticsearch是一个流行的开源搜索引擎,它可以将大量数据快速存储和检索。Elasticsearch还提供了强大的实时分析和聚合查询功能,数据模式更加灵活。它不需要预先定义固定的数据结构,可以随时添加或修改数据字段,而不需要进行繁琐的数据库迁移。横向扩展性......
  • Android11修改摄像头前后置方法,触觉智能RK3568开发板演示
    本文介绍在Android11系统下,修改摄像头前后置属性的方法。使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!内核修改配置修改相关内核设备树文件以下配置:ov5648:ov56......