luogu4365 秘密袭击 (生成函数+线段树合并+拉格朗日插值)
求所有可能联通块的第k大值的和,考虑枚举这个值:
$ans=\sum\limits_{i=1}^{W}{i\sum\limits_{S}{[i是第K大]}}$
设cnt[i]为连通块中值>=i的个数
$ans=\sum\limits_{i=1}^{W}{i\sum\limits_{S}{[cnt[i]>=K]-[cnt[i+1]>=K]}}$
$ans=\sum\limits_{i=1}^{W}{\sum\limits_{S}{[cnt[i]>=K]}}$
于是先考虑树上dp,设f[i][j][k]表示以i为根的连通块中,值>=j的数量为k的情况数
然后$ans=\sum\limits_{i=1}^{N}{\sum\limits_{j=1}^{W}{\sum\limits_{k=K}^{N}{f[i][j][k]}}}$
转移和背包类似,所以这样做是$O(N^2W)$的
考虑使用生成函数优化,设$F[i][j]=\sum{f[i][j][k]x^k}$,再设$G[i][j]=\sum{F[s][j]},i是s的祖先$
于是转移就变成了$F[i][j]*=(F[s][j]+1),G[i][j]+=G[s][j],G[i][j]+=F[i][j]$,其中s是i的孩子
同时有初值$F[i][j]=(d[i]>=j?x:1)$,答案就是G[1][*]的K~N项系数的和
然后当然不能真的去乘了..
考虑先将F和G用点值表达,最后再插回来
首先枚举x=1..N+1,然后给每个点i开动态开点的线段树维护F[i][j]和G[i][j]的值
然后用线段树合并来做对应位置的相乘和相加
具体来说,我们让线段树上的结点维护一个作用在$(f,g)$上的变换$(a,b,c,d)$,使得最终得到$(af+b,cf+d+g)$
然后也不难得到变换的乘法(有结合律但没有交换律)
然后就可以做了 复杂度我也不会分析 反正有可能跑的比暴力还慢
别忘了回收掉不用的点
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 #define fi first 6 #define se second 7 using namespace std; 8 typedef long long ll; 9 typedef unsigned long long ull; 10 typedef unsigned int ui; 11 typedef long double ld; 12 const int maxn=1700,maxp=3e6; 13 const int P=64123; 14 15 inline char gc(){ 16 return getchar(); 17 static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf; 18 return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++; 19 } 20 inline ll rd(){ 21 ll x=0;char c=gc();bool neg=0; 22 while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();} 23 while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc(); 24 return neg?(~x+1):x; 25 } 26 27 struct Node{ 28 int a,b,c,d; 29 Node(int _a=1,int _b=0,int _c=0,int _d=0){a=_a,b=_b,c=_c,d=_d;} 30 }val[maxp]; 31 Node operator *(Node x,Node y){ 32 return Node(1ll*x.a*y.a%P,(1ll*x.b*y.a+y.b)%P,(1ll*x.a*y.c+x.c)%P,(1ll*x.b*y.c+x.d+y.d)%P); 33 } 34 35 int N,K,W,dan[maxn],eg[maxn*2][2],egh[maxn],ect; 36 int ch[maxp][2],stk[maxp],sh,rt[maxn]; 37 int yy[maxn]; 38 39 inline void adeg(int a,int b){ 40 eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect; 41 } 42 43 inline int newnode(){ 44 int p=stk[sh--]; 45 assert(sh>=1); 46 ch[p][0]=ch[p][1]=0; 47 val[p]=Node(); 48 return p; 49 } 50 51 inline void delall(int &p){ 52 if(!p) return; 53 delall(ch[p][0]);delall(ch[p][1]); 54 stk[++sh]=p;p=0; 55 } 56 57 inline void pushdown(int p){ 58 if(!ch[p][0]) ch[p][0]=newnode(); 59 if(!ch[p][1]) ch[p][1]=newnode(); 60 val[ch[p][0]]=val[ch[p][0]]*val[p]; 61 val[ch[p][1]]=val[ch[p][1]]*val[p]; 62 val[p]=Node(); 63 } 64 65 void mul(int &p,int l,int r,int x,int y,Node z){ 66 if(!p) p=newnode(); 67 if(x<=l&&r<=y){ 68 val[p]=val[p]*z; 69 }else{ 70 int m=(l+r)>>1;pushdown(p); 71 if(x<=m) mul(ch[p][0],l,m,x,y,z); 72 if(y>=m+1) mul(ch[p][1],m+1,r,x,y,z); 73 } 74 } 75 76 int merge(int &p,int &q){ 77 if(!p||!q) return p|q; 78 if(!ch[p][0]&&!ch[p][1]) swap(p,q); 79 if(!ch[q][0]&&!ch[q][1]){ 80 val[p]=val[p]*Node(val[q].b,0,0,val[q].d); 81 return p; 82 } 83 pushdown(p),pushdown(q); 84 ch[p][0]=merge(ch[p][0],ch[q][0]); 85 ch[p][1]=merge(ch[p][1],ch[q][1]); 86 return p; 87 } 88 89 void dfs(int x,int f,int id){ 90 mul(rt[x],1,W,1,W,Node(0,1,0,0)); 91 for(int i=egh[x];i;i=eg[i][1]){ 92 int b=eg[i][0];if(b==f) continue; 93 dfs(b,x,id); 94 merge(rt[x],rt[b]); 95 delall(rt[b]); 96 } 97 mul(rt[x],1,W,1,dan[x],Node(id,0,0,0)); 98 mul(rt[x],1,W,1,W,Node(1,0,1,0)); 99 mul(rt[x],1,W,1,W,Node(1,1,0,0)); 100 } 101 102 int query(int p,int l,int r){ 103 if(!p) return 0; 104 if(l==r) return val[p].d; 105 int m=(l+r)>>1;pushdown(p); 106 return (query(ch[p][0],l,m)+query(ch[p][1],m+1,r))%P; 107 } 108 109 int fpow(int x,int y){ 110 int r=1; 111 while(y){ 112 if(y&1) r=1ll*r*x%P; 113 x=1ll*x*x%P,y>>=1; 114 }return r; 115 } 116 117 int l[maxn],tmp[maxn],ans[maxn]; 118 void calc(){ 119 l[0]=1; 120 for(int i=1;i<=N+1;i++){ 121 for(int j=i-1;j>=0;j--){ 122 l[j+1]=(l[j+1]+l[j])%P; 123 l[j]=-1ll*i*l[j]%P; 124 } 125 } 126 for(int i=1;i<=N+1;i++){ 127 int ib=-fpow(i,P-2); 128 tmp[0]=1ll*l[0]*ib%P; 129 for(int j=1;j<=N;j++){ 130 tmp[j]=1ll*(l[j]-tmp[j-1])*ib%P; 131 } 132 int k=0,x=1; 133 for(int j=0;j<=N;j++){ 134 k=(1ll*x*tmp[j]+k)%P; 135 x=1ll*x*i%P; 136 } 137 k=1ll*fpow(k,P-2)*yy[i]%P; 138 for(int j=0;j<=N;j++){ 139 ans[j]=(1ll*tmp[j]*k+ans[j])%P; 140 } 141 } 142 } 143 144 int main(){ 145 //freopen("","r",stdin); 146 N=rd(),K=rd(),W=rd(); 147 for(int i=1;i<=N;i++) dan[i]=rd(); 148 for(int i=1;i<N;i++){ 149 int a=rd(),b=rd(); 150 adeg(a,b);adeg(b,a); 151 } 152 for(int i=1;i<maxp-5;i++) stk[++sh]=i; 153 154 for(int i=1;i<=N+1;i++){ 155 dfs(1,0,i); 156 yy[i]=query(rt[1],1,W); 157 delall(rt[1]); 158 } 159 calc(); 160 int a=0; 161 for(int i=K;i<=N;i++) a=(a+ans[i])%P; 162 printf("%d\n",(a+P)%P); 163 return 0; 164 }
转载于:https://www.cnblogs.com/Ressed/p/10504966.html
luogu4365 秘密袭击 (生成函数+线段树合并+拉格朗日插值)相关推荐
- 【九省联考2018】秘密袭击【树形dp】【生成函数】【线段树合并】【多项式插值】
题意:nnn 个点的带点权的树,点权最大值为 www,求所有连通子图第 kkk 大权值之和模 641236412364123. n,w≤1666n,w\leq 1666n,w≤1666,时限 5s. ...
- 线段树合并与分裂维护树上最长上升子序列 + 点分治删点 ---- 2021 牛客多校第一场 C - Cut the tree(详解)
题目大意: 给你一个树,树上每个点都有一个权值valnodeval_{node}valnode,路径(u,v)(u,v)(u,v) 上所有点按顺序有序序列,令f(u,v)f(u,v)f(u,v)是这 ...
- 线段树分裂与合并 ---- 树上差分 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
题目链接 解题思路: 首先题目是对u,vu,vu,v这两条路径上面添加一个zzz,然后运用树上点的差分思想,对于分发路径u,vu,vu,v,我们在uuu上+1+1+1,在vvv上+1+1+1,在lca ...
- 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解
题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...
- 【BZOJ-3681】Arietta 网络流 + 线段树合并
3681: Arietta Time Limit: 20 Sec Memory Limit: 64 MB Submit: 182 Solved: 70 [Submit][Status][Discu ...
- BZOJ3526[Poi2014]Card——线段树合并
题目描述 有n张卡片在桌上一字排开,每张卡片上有两个数,第i张卡片上,正面的数为a[i],反面的数为b[i].现在,有m个熊孩子来破坏你的卡片了! 第i个熊孩子会交换c[i]和d[i]两个位置上的卡片 ...
- 【BZOJ5461】 【PKUWC2018】—Minimax(线段树合并优化dp)
传送门 发现其实就是左右2棵子树,左儿子选到某个值的概率就是 选最大值的概率∗右儿子的值比它小的概率选最大值的概率*右儿子的值比它小的概率选最大值的概率∗右儿子的值比它小的概率 +选最小值的概率∗右儿 ...
- [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...
- CF1037H Security——SAM+线段树合并
又是一道\(SAM\)维护\(endpos\)集合的题,我直接把CF700E的板子粘过来了QwQ 思路 如果我们有\([l,r]\)对应的\(SAM\),只需要在上面贪心就可以了.因为要求的是字典序比 ...
最新文章
- 360金融沈赟:只有适配实践的技术才能实现价值掘金
- tcpdump抓取mysql语句
- python爬虫面试题
- docker部署express项目
- C++开发的应用方向有哪些?
- 计算机二级access数据库考试题型,2016最新计算机二级Access数据库试题及答案
- win10无法运行jre java_Windows10系统安装不了jre的解决方法
- 深度学习花书+机器学习西瓜书电子版我找到了
- 百度网盘获取下载链接
- 关于automation服务器不能创建对象
- MPM模型及ab压力测试
- linux sar 分析,Linux性能测试分析命令_sar
- HTML制作导航条的方法
- 在Qt中使用OpenGL(二)
- 3月13日云栖精选夜读 | Serverless 风暴来袭,前端工程师如何应对?...
- 【ModuleNotFoundError 与 ImportError】之 most likely due to a circular import
- 对于HTML文档标题居中,导出word 和网页显示 问题
- 怎么释放C盘空间?清理C盘空间的4大方法分享!
- Tensor (张量) - 神经网络中的数据结构
- SAR ADC系列16:CDAC上机实践+作业
热门文章
- MacOS中Dock栏的设置和使用技巧,新手必看
- 【树莓派学习笔记】六、启用摄像头、实时视频、录像和截图
- [算法] vector删除元素
- [bash] 打包某目录(可以是绝对路径)下的指定扩展名的文件
- 重学java基础第十三课:java帝国的诞生
- React开发(127):引入icon的方式
- 前端学习(3262):js高级教程(5)数据变量和内存
- [html] 在两个iframe之间传递参数的方法有哪些?
- [css] 在sass中可以执行布尔运算吗?
- 前端学习(2799):实现资讯的结构和列表