洛谷题面传送门

神仙题。

首先考虑一个点的深度是什么,注意到对于笛卡尔树而言直接从序列的角度计算一个点的深度是不容易的,因为这样会牵扯到序列中多个元素,需要 fixed 的东西太多,计算起来太复杂了。因此考虑从树本身的角度计算一个点的深度。注意到对于一棵树上所有点 \(u\)​ 而言都有 \(dep_u=\sum\limits_{v}[\text{LCA}(u,v)=v]\)​,因此我们求解一个点 \(x\)​ 的答案时,可以枚举所有 \(u,v\)​ 并计算 \(v\)​ 对 \(u\)​ 的贡献,即,有多少个排列满足逆序对个数为 \(k\)​,且笛卡尔树上 \(v\)​ 为 \(u\)​​ 的祖先。并且我们还可以注意到,对于一个序列而言,其笛卡尔树上某两点存在祖先关系是存在充要条件转化的,具体来说,\(\text{LCA}(u,v)=v\) 当且仅当 \(a_v\) 为 \(a[\min(u,v)…\max(u,v)]\) 的最小值,因此我们只需求解以下问题:

有多少个排列 \(p\),满足其逆序对个数为 \(k\),且 \(a_v=\min\limits_{i=\min(u,v)}^{\max(u,v)}a_i\)

这个问题看似难以下手,因为外面就已经枚举了两维 \(u,v\) 了,里面这东西也无法直接组合数求解,需要用 DP 之类的东西,一弄最低就是 \(n^3\),直接爆炸,不过细想其实不用复杂度那么高。我们首先考虑如果没有第二个条件怎么求,我们设 \(dp_{i,j}\) 表示有多少个长度为 \(i\) 的排列有 \(j\) 个逆序对,考虑怎么转移,不难发现,对于长度为 \(i+1\) 的排列,我们总能找到唯一的 \(a_{i+1}\),满足 \(a_{i+1}\) 与前面 \(i\) 个数产生的逆序对数为 \(x(x\in[0,i])\),也就是说 \(dp_{i+1,j}=\sum\limits_{x=0}^idp_{i,j-x}\),前缀和优化一下即可,这个在 CF1542E2 Abnormal Permutation Pairs (hard version) 中就已经见过了。对于此题亦是如此,与经典问题不同的一点是,直接按照 \(1,2,3,\cdots,n\) 的位置填数会爆炸,因此考虑换个顺序,如果 \(u<v\) 那么我们就按照 \(u,u+1,u+2,\cdots,v,u-1,u-2,\cdots,1,v+1,v+2,\cdots,n\) 的顺序填数,否则我们按照 \(u,u-1,u-2,\cdots,v,u+1,u+2,\cdots,n,v-1,v-2,\cdots,1\) 的顺序填。不难发现按照这样的顺序填数之后,其他位置上的填法都和前面一样,即第 \(i\) 个填的数可以为排列逆序对数产生 \([0,i-1]\) 中任意一个数的贡献,唯独 \(v\) 只有一种填法。而两种情况的差别的,前一种情况 \(v\) 会对排列逆序对数产生 \(|u-v|\) 的贡献,而后一种不会,因此如果写成生成函数的形式,就是前一种情况的方案数为 \([x^k]·x^{|u-v|}\prod\limits_{i=0}^{|u-v|-1}(\sum\limits_{j=0}^ix^j)·\prod\limits_{i=|u-v|+1}^{n-1}(\sum\limits_{j=0}^ix^j)\),后一种情况的方案数为 \(x^{|u-v|}\prod\limits_{i=0}^{|u-v|-1}(\sum\limits_{j=0}^ix^j)·\prod\limits_{i=|u-v|+1}^{n-1}(\sum\limits_{j=0}^ix^j)\),注意到对于一对 \(u,v\) 而言,上面两个式子的值只与 \(|u-v|\) 有关,因此可以对所有 \(|u-v|\) 预处理一波答案,复杂度 \(\mathcal O(n^4)\)。如果你观察能力再强一些,你还能发现这式子可以写成背包的形式,你对前后缀各做一遍背包就可以 \(n^3\) 求解了。

const int MAXN=300;
const int MAXK=44850;
int n,k,mod;
int pre[MAXN+5][MAXK+5],suf[MAXN+5][MAXK+5];
int sum[MAXK+5],c1[MAXN+5],c2[MAXN+5];
int getsum(int l,int r){return (sum[r]-((!l)?0:sum[l-1])+mod)%mod;}
int main(){
scanf("%d%d%d",&n,&k,&mod);pre[0][0]=1;
for(int i=0;i<=k;i++) sum[i]=1;
for(int i=1;i<n;i++){
for(int j=0;j<=k;j++) pre[i][j]=getsum(j-i,j);
memset(sum,0,sizeof(sum));sum[0]=pre[i][0];
for(int j=1;j<=k;j++) sum[j]=(sum[j-1]+pre[i][j])%mod;
} suf[n][0]=1;
for(int i=0;i<=k;i++) sum[i]=1;
for(int i=n-1;~i;i--){
for(int j=0;j<=k;j++) suf[i][j]=getsum(j-i,j);
memset(sum,0,sizeof(sum));sum[0]=suf[i][0];
for(int j=1;j<=k;j++) sum[j]=(sum[j-1]+suf[i][j])%mod;
} c1[0]=c2[0]=pre[n-1][k];
for(int i=1;i<n;i++){
for(int j=0;j<=k;j++) c1[i]=(c1[i]+1ll*pre[i-1][j]*suf[i+1][k-j])%mod;
for(int j=0;j<=k-i;j++) c2[i]=(c2[i]+1ll*pre[i-1][j]*suf[i+1][k-i-j])%mod;
} for(int i=1;i<=n;i++){
int res=0;
for(int j=1;j<=n;j++){
if(j<=i) res=(res+c1[i-j])%mod;
else res=(res+c2[j-i])%mod;
} printf("%d%c",res," \n"[i==n]);
}
return 0;
}

洛谷 P5853 - [USACO19DEC]Tree Depth P(生成函数+背包)的更多相关文章

  1. 【题解】洛谷P1273 有线电视网(树上分组背包)

    次元传送门:洛谷P1273 思路 一开始想的是普通树形DP 但是好像实现不大好 观摩了一下题解 是树上分组背包 设f[i][j]为以i为根的子树中取j个客户得到的总价值 我们可以以i为根有j组 在每一 ...

  2. 【洛谷】P1541 乌龟棋(四维背包dp)

    题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...

  3. 【题解】洛谷P1941 [NOIP2014TG] 飞扬的小鸟(背包DP)

    次元传送门:洛谷P1941 思路 从题意可知 在每个单位时间内 可以无限地向上飞 但是只能向下掉一次 所以我们可以考虑运用背包解决这道题 上升时 用完全背包 下降时 用01背包 设f[x][y]为在坐 ...

  4. 【题解】洛谷P1541 [NOIP2010TG] 乌龟棋(类似背包的DP)

    题目来源:洛谷P1541 思路 类似背包的题 总之就是四种卡牌取的先后顺序不同导致的最终ans不同 所以我们用一个四维数组每一维分别表示第几种取了几张的最大分数 然后就是简单DP解决 代码 #incl ...

  5. 洛谷P5206 [WC2019] 数树(生成函数+容斥+矩阵树)

    题面 传送门 前置芝士 矩阵树,基本容斥原理,生成函数,多项式\(\exp\) 题解 我也想哭了--orz rqy,orz shadowice 我们设\(T1,T2\)为两棵树,并定义一个权值函数\( ...

  6. [USACO19DEC]Tree Depth P

    题意 求逆序对为\(k\)的\(n\)排列中,生成的笛卡尔数,每个位置的深度和.\(n\le 300\) 做法 设\(f_{k}\)为\(n\)排列中逆序对为\(k\)的个数,其生成函数为:\[\pr ...

  7. 【洛谷P4178】Tree

    题面 题解 感觉和\(CDQ\)分治一样套路啊 首先,构建出点分树 对于每一层分治重心,求出它到子树中任意点的距离 然后\(two-pointers\)计算满足小于等于\(K\)的点对数目,加入答案 ...

  8. BZOJ2654 & 洛谷2619:tree——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2654 https://www.luogu.org/problemnew/show/P2619 给你 ...

  9. 洛谷4178 BZOJ1468 Tree题解点分治

    点分治的入门练习. 题目链接 BZOJ的链接(权限题) 关于点分治的思想我就不再重复了,这里重点说一下如何判重. 我们来看上图,假设我们去除了1节点,求出d[2]=1,d[3]=d[4]=2 假设k为 ...

随机推荐

  1. 指标统计:基于流计算 Oceanus(Flink) 实现实时 UVPV 统计

    作者:吴云涛,腾讯 CSIG 高级工程师导语 | 最近梳理了一下如何用 Flink 来实现实时的 UV.PV 指标的统计,并和公司内微视部门的同事交流.然后针对该场景做了简化,并发现使用 Flink ...

  2. vue3.x自定义组件双向数据绑定v-model

    vue2.x 语法 在 2.x 中,在组件上使用 v-model 相当于绑定 value prop 并触发 input 事件: <ChildComponent v-model="pag ...

  3. Alpha Scrum Meeting汇总

    第一次Alpha Scrum Meeting 第二次Alpha Scrum Meeting 第三次Alpha Scrum Meeting 第四次Alpha Scrum Meeting 第五次Alpha ...

  4. Vue3+Typescript+Node.js实现微信端公众号H5支付(JSAPI v3)教程--各种填坑

    ----微信支付文档,不得不说,挺乱!(吐槽截止) 功能背景 微信公众号中,点击菜单或者扫码,打开公众号中的H5页面,进行支付. 一.技术栈 前端:Vue:3.0.0,typescript:3.9.3 ...

  5. python画图的工具及网站

    ①Gallery - Matplotlib 3.4.3 documentation 学会模仿并超越 ②Examples - Apache ECharts js网页端动态展示 ③WEB色見本 原色大辞典 ...

  6. Redis INFO CPU 信息详解

    一.INFO CPU 通过INFO CPU命令可以查看Redis进程对于CPU的使用情况,如下: 这几个字段的含义如下所示: used_cpu_sys: System CPU consumed by ...

  7. 西邮Linux兴趣小组第一次技术分享会

    2016年10月30日晚,西邮Linux兴趣小组技术分享会在西安邮电大学长安校区东区逸夫教学楼FF305室成功举办.200多名来自全校不同专业的15,16级同学参加了此次分享会. 分享会于20:00正 ...

  8. 从0到1使用Kubernetes系列(六):数据持久化实战

    本文是从 0 到 1 使用 Kubernetes 系列第六篇,上一篇<从 0 到 1 使用 Kubernetes 系列(五):Kubernetes Scheduling>介绍了 Kuber ...

  9. 【java+selenium3】时间控件 (九)

    1.问题描述: 在应用selenium实现web自动化时,经常会遇到处理日期控件点击问题,手工很简单,可以一个个点击日期控件选择需要的日期,但自动化执行过程中,完全复制手工这样的操作就有点难了. 如图 ...

  10. 由于xftp打开target目录,导致maven编译的时候target目录无法访问,打包失败

    由于xftp打开target目录,导致maven编译的时候target目录无法访问,打包失败: 在xftp里关闭target目录就可以了...无时不在的坑