[XSY] 树与图(树形DP、生成函数、分治NTT、重链剖分)

树与图

  • 如果真的在图上跑算法,那么光建图复杂度就O(n2logn)O(n^2logn)O(n2logn)了,这显然不可行。所以一定要把 在图上的操作 转换成 在树上的操作
  • 在图上删去点u,相当于在树上删去u到根节点的链,并把u的整棵子树删掉
  • 如果我们枚举算法可能产生的所有过程,然后再去求每个过程对应的删点次数,那么光枚举过程就已经可以T爆了
  • 所以我们只能枚举删点次数,然后求出该删掉次数对应多少种过程
  • 这可以用树形DP实现,时间复杂度O(n3)O(n^3)O(n3)
  • 可以想到用生成函数进一步优化,即用次数来代表删点次数,系数来代表可能过程种数,这样合并两棵子树时直接用NTT把两棵子树的多项式乘起来即可
  • 这样会产生两个问题:
  1. 代码中每一步合并乘的Cj+kkC_{j+k}^{k}Cj+kk怎么办?

  2. NTT的时间复杂度是O(nlogn)O(nlogn)O(nlogn)(这里n指多项式的最高次数)\color{Red}(这里n指多项式的最高次数)(n),这样总时间复杂度就是O(n3logn)O(n^3logn)O(n3logn),怎么还变大了?

    就是这两个问题让我在考场上没有继续写下去

  • 对于第一个问题,我后来想到,其实不一定要在DP过程中乘Cj+kkC_{j+k}^{k}Cj+kk,DP完后再统一乘(删点次数)!(删点次数)!来定序也是可行的
  • 对于第二个问题,在更新u时,直接用 分治NTT 把u的所有儿子上的多项式 一起 乘起来,不要那么傻逼想着用NTT一个接一个乘
    这样时间复杂度降为O(n2log2n)O(n^2log^2n)O(n2log2n),但还是会T
  • 题目的时间复杂度很大程度上取决于NTT时多项式的最高次数,而多项式次数与删点次数有关,所以考虑一下我们最多能删几个点
  • 发现所选的要删的点满足如下规律:所选的任意两个点都不互为祖先关系,且从根到每个叶子的路径上都恰好有一个被选择的点
  • u点的多项式的最高次数<=u子树内叶节点的个数\color{Red}u点的多项式的最高次数<=u子树内叶节点的个数u<=u,进一步地,因为每个节点的多项式最高次数至少为1,所以u点的多项式最多是(u子树内叶节点个数)个多项式相乘的结果\color{Red}u点的多项式最多是(u子树内叶节点个数)个多项式相乘的结果u(u)
  • leafuleaf_uleafu表示u的子树中叶子的个数,则在u点分治NTT的时间总和<=leafu(log2leafu)<=leaf_u(log^2leaf_u)<=leafu(log2leafu),整道题的总时间<=∑u=1nleafu(log2leafu)<=\sum_{u=1}^{n}leaf_u(log^2leaf_u)<=u=1nleafu(log2leafu)
  • 考虑两种极端情况,一种是菊花图,一种是一条很长的树链,上面随机的挂上一些类似菊花图(深度小但点度数大)的子树
  • 按照上面的做法,菊花图的时间复杂度可以做到O(nlog2n)O(nlog^2n)O(nlog2n),树链的时间复杂度却逼近O(n2log2n)O(n^2log^2n)O(n2log2n)
  • 我们考虑给树链换一种做法:
    枚举在链上删了哪个点,这样一来整条链和被删点的子树都会被删除,而被删点上方的子树不会被删除,并且相互独立了。
    因此,如果链上的点的多项式为F1(x),F2(x),F3(x)...F_1(x),F_2(x),F_3(x)...F1(x),F2(x),F3(x)...(按点深度由浅到深编号),那么最后求出这条链的多项式为:F1(x)+F1(x)F2(x)+F1(x)F2(x)F3(x)...F_1(x)+F_1(x)F_2(x)+F_1(x)F_2(x)F_3(x)...F1(x)+F1(x)F2(x)+F1(x)F2(x)F3(x)...
    用分治NTT做,总时间<=leaf1(log2leaf1)<=leaf_1(log^2leaf_1)<=leaf1(log2leaf1),所以时间复杂度为O(nlog2n)O(nlog^2n)O(nlog2n)
  • 考虑把这两种做法结合起来,即对树进行重链剖分,然后对每个节点的轻儿子分治NTT对每条重链分治 NTT
  • 具体来说,设fu(x)f_u(x)fu(x)表示u点的多项式
    深搜遍历每个节点,假设当前遍历到u
    若u为叶子节点:fu(x)=xf_u(x)=xfu(x)=x,返回
    若不是:执行下述步骤
    ①若节点u有轻儿子:fu(x)=∏v∈lightsonfv(x)f_u(x)=\prod_{v\in lightson}f_v(x)fu(x)=vlightsonfv(x)
    若没有:fu(x)=1f_u(x)=1fu(x)=1
    ②若节点为重链端点:
    (设这条重链上的点由浅至深分别为p1,p2,⋯,pkp_1,p_2,⋯,p_kp1,p2,,pk。显然,p1p_1p1为链头,pkp_kpk为叶子节点。)
    fp1(x)=fp1(x)+fp1(x)fp2(x)+fp1(x)fp2(x)fp3(x)+...+fp1(x)fp2(x)fp3(x)...fpk−1+xf_{p_1}(x)=f_{p_1}(x)+f_{p_1}(x)f_{p_2}(x)+f_{p_1}(x)f_{p_2}(x)f_{p_3}(x)+...+f_{p_1}(x)f_{p_2}(x)f_{p_3}(x)...f_{p_{k-1}}+xfp1(x)=fp1(x)+fp1(x)fp2(x)+fp1(x)fp2(x)fp3(x)+...+fp1(x)fp2(x)fp3(x)...fpk1+x
    +x+x+x是因为要考虑删去自己的情况)
  • 分析一下这样做的时间复杂度,整道题的总时间<=∑u∈topleafu(log2leafu)+∑u=1n(∑v∈lightsonuleafv)[log2(∑v∈lightsonuleafv)]<=\sum_{u\in top}leaf_u(log^2leaf_u)+\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)[log^2(\sum_{v\in lightson_u}leaf_v)]<=utopleafu(log2leafu)+u=1n(vlightsonuleafv)[log2(vlightsonuleafv)]
  • ∑u∈topleafu(log2leafu)<=∑u∈topleafu(log2n)=log2n∑u∈topleafu\sum_{u\in top}leaf_u(log^2leaf_u)<=\sum_{u\in top}leaf_u(log^2n)=log^2n\sum_{u\in top}leaf_uutopleafu(log2leafu)<=utopleafu(log2n)=log2nutopleafu 。因为每个叶子节点到根节点的路径上最多有lognlognlogn条重链,而每个叶子节点又只在其到根节点的路径上的重链头处对∑u∈topleafu\sum_{u\in top}leaf_uutopleafu有1的贡献,所以∑u∈topleafu<=nlogn\sum_{u\in top}leaf_u<=nlognutopleafu<=nlogn∑u∈topleafu(log2leafu)<=nlog3n\sum_{u\in top}leaf_u(log^2leaf_u)<=nlog^3nutopleafu(log2leafu)<=nlog3n
  • ∑u=1n(∑v∈lightsonuleafv)[log2(∑v∈lightsonuleafv)]<=∑u=1n(∑v∈lightsonuleafv)(log2n)=log2n∑u=1n(∑v∈lightsonuleafv)\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)[log^2(\sum_{v\in lightson_u}leaf_v)]<=\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)(log^2n)=log^2n\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)u=1n(vlightsonuleafv)[log2(vlightsonuleafv)]<=u=1n(vlightsonuleafv)(log2n)=log2nu=1n(vlightsonuleafv) 。因为每个叶子节点到根节点的路径上最多有lognlognlogn条轻边,即每个叶子节点最多只在lognlognlogn个祖先处对∑u=1n(∑v∈lightsonuleafv)\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)u=1n(vlightsonuleafv)有1的贡献,所以∑u=1n(∑v∈lightsonuleafv)<=nlogn\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)<=nlognu=1n(vlightsonuleafv)<=nlogn∑u=1n(∑v∈lightsonuleafv)[log2(∑v∈lightsonuleafv)]<=nlog3n\sum_{u=1}^{n}(\sum_{v\in lightson_u}leaf_v)[log^2(\sum_{v\in lightson_u}leaf_v)]<=nlog^3nu=1n(vlightsonuleafv)[log2(vlightsonuleafv)]<=nlog3n
  • 因此总时间复杂度是O(nlog3n)O(nlog^3n)O(nlog3n),但由于树剖logloglog小和跑不满等原因可以跑过

(最后树剖分轻重儿子维护的处理类似这题,可以一起记忆)

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int N=100010;
const int M=250000;
struct Edge{int v,nxt;
}edge[N];
int n,cnt,head[N];
int fa[N],sz[N],son[N],ind,dfn[N],rnk[N],top[N],bot[N];
int rev[M],inv[M],w[20][M],iw[20][M],A[M],B[M];
vector<int> poly[N],f[N<<2],g[N<<2];
int add(int a,int b){a=a+b;if(a>mod) return a-mod;return a;
}
int dec(int a,int b){a=a-b;if(a<0) return a+mod;return a;
}
int mul(int a,int b){return 1ll*a*b%mod;
}
int power(int a,int b){int res=1;while(b){   if(b&1){res=mul(res,a);}b>>=1;a=mul(a,a);}return res;
}
void init(int len){inv[1]=1;for(int i=2;i<=len;i++) inv[i]=mul(inv[mod%i],dec(mod,mod/i));for(int i=1,t=0;i<len;i<<=1,t++){int wn=power(3,(mod-1)/i/2),iwn=power(wn,mod-2);for(int j=0;j<len;j+=(i<<1)){int w=1,iw=1;for(int k=j;k<j+i;k++,w=mul(w,wn),iw=mul(iw,iwn)){::w[t][k]=w;::iw[t][k]=iw;}}}
}
void NTT(int a[],int len,int op){//op=0:系数转点值,op=1:点值转系数 for(int i=0;i<len;i++){rev[i]=(rev[i>>1]>>1)|((i&1)*(len>>1));if(i<rev[i])swap(a[i],a[rev[i]]);}for(int i=1,t=0;i<len;i<<=1,t++){for(int j=0;j<len;j+=(i<<1)){int x,y;for(int k=j;k<j+i;k++){x=a[k];if(!op) y=mul(w[t][k],a[k+i]);else if(op) y=mul(iw[t][k],a[k+i]);a[k]=add(x,y);a[k+i]=dec(x,y);}}}if(op){for(int i=0;i<len;i++)a[i]=mul(a[i],inv[len]);} 
}
vector<int> operator + (const vector<int> &a,const vector<int> &b){int n=a.size(),m=b.size();vector<int> c(max(n,m));for(int i=0;i<n;i++) c[i]=a[i];for(int i=0;i<m;i++) c[i]=add(c[i],b[i]);return c;
}
vector<int> operator * (const vector<int> &a,const vector<int> &b){int n=a.size(),m=b.size();vector<int> c(n+m-1);int len;for(len=1;len<=n+m;len<<=1);for(int i=0;i<len;i++){A[i]=i<n?a[i]:0;B[i]=i<m?b[i]:0;}NTT(A,len,0);NTT(B,len,0);for(int i=0;i<len;i++)A[i]=mul(A[i],B[i]);NTT(A,len,1);for(int i=0;i<n+m-1;i++) c[i]=A[i];return c;
}
void addedge(int u,int v){edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
void dfs1(int u){sz[u]++;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;dfs1(v);sz[u]+=sz[v];if(sz[v]>sz[son[u]]) son[u]=v;}
}
void dfs2(int u,int tp){dfn[u]=++ind;rnk[ind]=u;top[u]=tp;bot[tp]=u;if(!son[u]) return;dfs2(son[u],tp);for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v!=son[u]) dfs2(v,v);}
}
void solve(vector<int> &sons,int u,int l,int r){if(l==r){f[u]=poly[sons[l]];return;}int mid=(l+r)>>1;solve(sons,u<<1,l,mid);solve(sons,u<<1|1,mid+1,r);f[u]=f[u<<1]*f[u<<1|1];f[u<<1].clear();f[u<<1|1].clear();
}
void merge(int u,int l,int r){if(l==r){f[u]=g[u]=poly[rnk[l]];return;}int mid=(l+r)>>1;merge(u<<1,l,mid);merge(u<<1|1,mid+1,r);f[u]=f[u<<1]*f[u<<1|1];g[u]=g[u<<1]+f[u<<1]*g[u<<1|1];//g=f1+f1f2+f1f2f3+...f[u<<1].clear();f[u<<1|1].clear();g[u<<1].clear();g[u<<1|1].clear();
}
void dp(int u){if(!son[u]){poly[u].push_back(0);//0*x^0poly[u].push_back(1);//1*x^1return;}dp(son[u]);vector<int> lis;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v!=son[u]){dp(v);lis.push_back(v);}}if(lis.size()){solve(lis,1,0,lis.size()-1);//分治NTT合并轻儿子信息 poly[u]=f[1];}else{ poly[u].push_back(1);//1*x^0}if(u==top[u]){merge(1,dfn[u],dfn[bot[u]]-1);//分治NTT合并重链信息 //注意-1poly[u].clear();poly[u].push_back(0);//0*x^0for(int i=0,sz=g[1].size();i<sz;i++){poly[u].push_back(g[1][i]);}poly[u][1]=add(poly[u][1],1);//x^1项的次数+1 }
}
int main(){scanf("%d",&n);for(int i=2;i<=n;i++){scanf("%d",&fa[i]);addedge(fa[i],i);}dfs1(1);dfs2(1,1);int len=1;while(len<=n) len<<=1;init(len);dp(1);while((int)poly[1].size()<=n) poly[1].push_back(0);int ans=0,fac=1,x;for(int i=1;i<=n;i++){scanf("%lld",&x);fac=mul(fac,i);ans=add(ans,mul(x,mul(poly[1][i],fac)));}printf("%lld\n",ans);return 0;
} 

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

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

相关文章

520 钻石争霸赛 题解

说好的钻石难度&#xff0c;结果本人菜的一地。。只有88分。。。。 文章目录7-1 考试周7-2 真的恭喜你7-3 平均成绩7-4 古风AB难度开始上升7-5 猜近似数字7-6 随机输一次7-7 阶乘的非零尾数7-8 三足鼎立前四题十分钟AC后两题二十分钟自闭第五题玄学卡点不知为何7-1 考试周 模拟…

.NET Core 跨平台物联网框架 ServerSuperIO.Core,一套设备驱动通吃嵌入式、上位机、云服务...

一、概述我们的大数据平台&#xff08;云&#xff09;平台的数据接收服务基于ServerSuperIO开发&#xff0c;因为集成的功能比较多&#xff0c;无法实现跨平台&#xff0c;现在跑在Windows下。但是云端体系化、标准化建设&#xff0c;跨平台是必走的技术路线。在ServerSuperIO基…

P3243-[HNOI2015]菜肴制作【拓扑排序,优先队列】

正题 题目链接:https://www.luogu.com.cn/problem/P3243 题目大意 nnn个数&#xff0c;有mmm个要求形如xxx在yyy的前面&#xff0c;现在要求在i−1i-1i−1尽量靠前的情况下iii尽量靠前(i>1)(i>1)(i>1) 求这个序列 解题思路 这个很显然要求是张有向图无环图&#xff…

【贪心】雷达装置(ybtoj 贪心-1-2)

雷达装置 ybtoj 贪心-1-2 题目大意 在平面直角坐标系中有n个点&#xff0c;现在让你在x轴上布置雷达&#xff0c;雷达可以的侦查半径为d&#xff0c;问你最少布置多少个雷达 输入样例 3 2 1 2 -3 1 2 1输出样例 2数据范围 1⩽n⩽1031\leqslant n \leqslant 10^31⩽n⩽103…

[XSY] 传统游戏(DP、容斥)

传统游戏 看到题&#xff0c;第一想法是设dp[k][s]dp[k][s]dp[k][s]表示选了kkk个数&#xff0c;当前异或和为sss的方案数&#xff0c;但这样产生一个问题&#xff1a;要如何保证所选的数不重复且无序呢&#xff1f;一种方法是修改状态&#xff1a;我们增设一维iii&#xff0c…

asp.net core添加全局异常处理及log4net、Nlog应用

一、介绍此篇文章将会介绍项目的全局异常收集以及采用log4net或者NLog记录。众所周知&#xff0c;一旦自己的项目报错&#xff0c;如果没有进行处理都是显示不友好的&#xff0c;有得甚至直接爆出错误页面&#xff0c;看的也是很奇怪。为了避免出现这样的错误以及在错误出现的时…

牛客网 【每日一题】5月20日题目 简单瞎搞题

比赛链接 文章目录题目描述题解&#xff1a;代码&#xff1a;题目描述 输入描述: 第一行一个数 n。 然后 n 行&#xff0c;每行两个数表示 li,ri。 输出描述: 输出一行一个数表示答案。 示例1 输入 5 1 2 2 3 3 4 4 5 5 6输出 26备注: 1 ≤ n , li , ri ≤ 100 题解&#xf…

P6688-可重集【字符串hash,线段树】

正题 题目链接:https://www.luogu.com.cn/problem/P6688 解题思路 nnn个数&#xff0c;每次有操作 修改一个数询问两个区间是否他们中的元素分别组成的可重集合A,BA,BA,B&#xff0c;满足对于每个AiBikA_iB_ikAi​Bi​k其中kkk是一个相同的数 解题思路 先不考虑kkk的问题 我…

【贪心】畜栏预定(ybtoj 贪心-1-3)

畜栏预定 ybtoj 贪心-1-3 题目大意 有n头牛&#xff0c;每头牛会在某一连续时间段吃草&#xff0c;问你同一时间最对有多少头牛&#xff0c;最后对于每一头牛给一个吃草的位置&#xff0c;使得同一时间内吃草的牛的位置不重合 输入样例 5 1 10 2 4 3 6 5 8 4 7输出样例 4…

ASP.NET Core 2.0利用MassTransit集成RabbitMQ

在ASP.NET Core上利用MassTransit来集成使用RabbitMQ真的很简单&#xff0c;代码也很简洁。近期因为项目需要&#xff0c;我便在这基础上再次进行了封装&#xff0c;抽成了公共方法&#xff0c;使得使用RabbitMQ的调用变得更方便简洁。那么&#xff0c;就让咱们来瞧瞧其魅力所在…

简单的数据结构题(多项式、拉格朗日插值、线段树)

简单的数据结构题 首先考虑计算要求的式子&#xff0c;不妨设l1,rnl1,rnl1,rn。 ∑i1naik∏j̸i1−aiajai−aj\sum_{i1}^{n}a_i^k\prod_{j\noti}\frac{1-a_ia_j}{a_i-a_j}∑i1n​aik​∏j​i​ai​−aj​1−ai​aj​​ ∑i1naik∏j̸i1ai−aj∏j̸i(1−aiaj)\sum_{i1}^{n}a_…

牛客网 【每日一题】5月21日题目 图的遍历

链接&#xff1a; 文章目录题目描述题解代码&#xff1a;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld题目描述 小sun最近为了应付考试&#xff0c;正在复习图论&#xff0c;他现在学…

P4306-[JSOI2010]连通数【bitset】

正题 题目链接:https://www.luogu.com.cn/problem/P4306 题目大意 nnn个点的有向图&#xff0c;求图上可以相互到达点数。 解题思路 就是bitsetbitsetbitset这个黑科技的模板&#xff0c;首先是传递闭包 fi,jfi,k∣fk,jf_{i,j}f_{i,k}|f_{k,j}fi,j​fi,k​∣fk,j​也就是如果…

【贪心】国王游戏(ybtoj 贪心-1-4)

国王游戏 ybtoj 贪心-1-4 题目大意 有一个国王和n个大臣 每人左右手分别有一个数&#xff0c;现在然你对大臣们排列&#xff08;国王在第一个&#xff09; 每个大臣所得金币是前面的人左手上的数的积除以他右手上的数 现在问你获得金币最多的大臣最少得多少金币 样例输入 …

《通过C#学Proto.Actor模型》之 HelloWorld

在微服务中&#xff0c;数据最终一致性的一个解决方案是通过有状态的Actor模型来达到&#xff0c;那什么是Actor模型呢&#xff1f;Actor是并行的计算模型&#xff0c;包含状态&#xff0c;行为&#xff0c;并且包含一个邮箱&#xff0c;来异步处理消息。关于Actor的介绍可参考…

牛客网【每日一题】5月22日 [CQOI2009]中位数图

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 给出1~n的一个排列&#xff0c;统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有…

[XSY] 计数(DP,NTT,分治)

计数 考虑转化题目&#xff0c;变为网格上有若干个点&#xff0c;要从(0,0)(0,0)(0,0)走到(n,an1)(n,a_{n1})(n,an1​) &#xff0c;每一步只能往右走一步或往上走一步&#xff0c;且若当前在(i,j)(i,j)(i,j) &#xff0c;必须满足0≤j≤ai10\leq j\leq a_{i1}0≤j≤ai1​&…

P3700-[CQOI2017]小Q的表格【分块,欧拉函数】

正题 题目链接:https://www.luogu.com.cn/problem/P3700 题目大意 一个n∗nn*nn∗n个数的数字表格&#xff0c;开始位置(a,b)(a,b)(a,b)上的是a∗ba*ba∗b。数字表格需满足以下条件 对于任意(a,b)(a,b)(a,b)有f(a,b)f(b,a)f(a,b)f(b,a)f(a,b)f(b,a)对于任意(a,b)(a,b)(a,b)有…

.Net Core应用框架Util介绍(一)

距离上次发文&#xff0c;已经过去了三年半&#xff0c;这几年技术更新节奏异常迅猛&#xff0c;.Net进入了跨平台时代&#xff0c;前端也被革命性的颠覆。回顾2015年&#xff0c;正当我还沉迷于JQuery EasyUi的封装时&#xff0c;突然意识到技术已经过时。JQuery在面对更加复…

牛客网 【每日一题】5月26日题目精讲 [JSOI2007]建筑抢修

链接&#xff1a; 文章目录题目描述题意&#xff1a;题解&#xff1a;题目描述 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏&#xff1a;经过了一场激烈的战斗&#xff0c;T部落消灭了所有z部落的入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤&#xf…