[COCI2015-2016#1] RELATIVNOST

RELATIVNOST の 传送门

线段树优化 dp 已经有很多题解讲的很好了。

dp 状态是一样的,但是一般的线段树优化 dp 空间要开 4n,而且只利用到线段树的一点点功能(单点修改),所以可以先优化空间,从 4n 优化到 2n

如下图所示。

如果用线段树优化 dp 的方法会导致树不止 logn+1 层,所以可以从下往上建树来保证最多 logn+1 层。

就直接将叶子节点赋值,其余 logn 层的答案就同线段树的 dp 一样更新。

然后每次询问都直接从要修改的点 p 所对应的叶子节点依次向上更新。

p 对应的叶子节点就是 p+n1,向上就直接当前的节点 now 改为 now2 即可。

C 风格的代码。

#include <stdio.h>
int p,A,B,n,c,Q,a[400005],b[400005],t[400005][21];
int minn(int a,int b) {return a>b?b:a;}
signed main() {
scanf("%d%d",&n,&c);
for(int i=1;i<=n;++i) scanf("%d",a+i),a[i]%=10007;
for(int i=1;i<=n;++i) scanf("%d",b+i),a[i]%=10007;
for(int i=1;i<=n;++i) t[n+i-1][0]=b[i],t[n+i-1][1]=a[i];
for(int p=n-1;p;--p)
for(int i=0;i<=c;++i)
for(int j=0;j<=c;++j)
t[p][minn(i+j,c)]+=1ll*t[p<<1][i]*t[p<<1|1][j]%10007,
t[p][minn(i+j,c)]%=10007;
scanf("%d",&Q);
while(Q--) {
scanf("%d%d%d",&p,&A,&B);
A%=10007,B%=10007;
p+=n-1;
t[p][0]=B,t[p][1]=A;
for(p>>=1;p;p>>=1) {
for(int i=0;i<=c;++i) t[p][i]=0;
for(int i=0;i<=c;++i)
for(int j=0;j<=c;++j)
t[p][minn(i+j,c)]+=1ll*t[p<<1][i]*t[p<<1|1][j]%10007,
t[p][minn(i+j,c)]%=10007;
}
printf("%d\n",t[1][c]);
}
return 0;
}
posted @   SilverLi  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示