「SLYZ Online Judge#74 Be」
昊哥从牛客搬的,懒得找原题了
题意就是多组询问,每次询问一条树上路径,将这条路径上的点拿下来做\(0/1\)背包,求使得点权和为\(K\)的倍数的方案有几种
\(n<=200000,K<=50,Q<=500000\)
首先这确实是一个背包,我们可以直接用树剖和线段树来维护这些路径,线段树上每个节点存一个数组\(dp[i][j]\),表示\(i\)这个区间选择出的数\(mod\ K=j\)的方案数
之后发现我们每次合并都是一个卷积,于是复杂度\(O(Qk^2logn)\),可以用\(NTT\)优化到\(O(Qklognlogk)\),但是并没有什么用
正解点分治,我们把询问离线,处理好每一组询问在那一个分治中心被处理到
处理当前分治重心的时候,我们直接求出每一个点到分治重心的\(dp\)数组,之后合并答案,由于这个时候我们只需要求\(dp[0]\),所以合并答案\(O(k)\)时间内就能完成
代码
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define LL long long
#define re register
#define inf 999999999
#define maxn 500005
const LL mod=998244353;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt;}e[maxn<<1];
struct Ask{int x,y,l,rk;}q[maxn];
std::vector<int> v[maxn],t[maxn];
int sum[maxn],mx[maxn],vis[maxn],col[maxn];
int head[maxn],dfn[maxn],st[maxn],Ans[maxn],a[maxn];
int n,m,num,S,now,rt,R,__,Top,K;
inline int cmp(Ask A,Ask B) {return dfn[A.l]<dfn[B.l];}
inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
LL dp[2][maxn][50];
void getroot(int x,int fa) {
sum[x]=1,mx[x]=0;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
getroot(e[i].v,x);sum[x]+=sum[e[i].v];
if(sum[e[i].v]>mx[x]) mx[x]=sum[e[i].v];
}
mx[x]=max(mx[x],S-sum[x]);
if(mx[x]<now) now=mx[x],rt=x;
}
void paint(int x,int fa,int c,int now) {
col[x]=c;st[++Top]=x;
for(re int i=0;i<t[x].size();i++) {
if(col[q[t[x][i]].x]&&col[q[t[x][i]].x]!=c) q[t[x][i]].l=now;
if(col[q[t[x][i]].y]&&col[q[t[x][i]].y]!=c) q[t[x][i]].l=now;
}
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||fa==e[i].v) continue;
paint(e[i].v,x,c,now);
}
}
void rebuild(int x) {
vis[x]=1;dfn[x]=++__;
int cnt=1;Top=0;col[x]=1;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
cnt++;paint(e[i].v,0,cnt,x);
}
while(Top) col[st[Top--]]=0;col[x]=0;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
S=sum[e[i].v],now=inf,getroot(e[i].v,0);
v[x].push_back(rt),rebuild(rt);
}
}
void getdis(int x,int fa,int o) {
if(o) st[++Top]=x;
for(re int i=0;i<K;i++)
dp[o][x][i]=dp[o][fa][i];
for(re int i=0;i<K;i++)
dp[o][x][(i+a[x])%K]+=dp[o][fa][i],dp[o][x][(i+a[x])%K]%=mod;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||fa==e[i].v) continue;
getdis(e[i].v,x,o);
}
}
inline void clear(int x) {
memset(dp[0][x],0,sizeof(dp[0][x]));
memset(dp[1][x],0,sizeof(dp[1][x]));
}
void dfs(int x) {
vis[x]=1;
Top=0;st[++Top]=x;dp[1][x][0]=1;dp[1][x][a[x]]++,dp[0][x][0]=1;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
getdis(e[i].v,x,0);getdis(e[i].v,x,1);
}
while(q[now].l==x&&now<=m) {
LL ans=0;int ls=q[now].x,rs=q[now].y;
for(re int i=0;i<K;i++)
ans+=(dp[1][ls][i]*dp[0][rs][(K-i)%K]%mod),ans%=mod;
Ans[q[now].rk]=ans,now++;
}
while(Top) clear(st[Top--]);
for(re int i=0;i<v[x].size();i++) dfs(v[x][i]);
}
signed main() {
n=read(),K=read();
for(re int x,y,i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
for(re int i=1;i<=n;i++) a[i]=read()%K;m=read();
for(re int i=1;i<=m;i++)
q[i].x=read(),q[i].y=read(),q[i].rk=i,t[q[i].x].push_back(i),t[q[i].y].push_back(i);
for(re int i=1;i<=m;i++) if(!q[i].l) q[i].l=q[i].x;
S=n,now=inf,getroot(1,0);R=rt;rebuild(rt);
std::sort(q+1,q+m+1,cmp);
memset(vis,0,sizeof(vis));now=1;dfs(R);
for(re int i=1;i<=m;i++) printf("%d\n",Ans[i]);
return 0;
}
「SLYZ Online Judge#74 Be」的更多相关文章
- #6034. 「雅礼集训 2017 Day2」线段游戏 李超树
#6034. 「雅礼集训 2017 Day2」线段游戏 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统 ...
- 【loj6034】「雅礼集训 2017 Day2」线段游戏
#6034. 「雅礼集训 2017 Day2」线段游戏 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:Special Judge 上传者: 匿名 题目描述 ...
- 「Mobile Testing Summit China 2016」 中国移动互联网测试大会-议题征集
时至北京盛夏,一场由 TesterHome 主办的关于移动互联网测试技术的盛会正在紧锣密鼓的筹备中.只要你关注软件质量,热爱测试,期待学习,都欢迎你加入这次移动测试技术大会中和我们一起分享经验.探讨话 ...
- 【翻译】西川善司「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,前篇(2)
Lighting和Shading(2)镜面反射的控制和模拟次级表面散射技术 http://www.4gamer.net/games/216/G021678/20140703095/index_2.ht ...
- 「七天自制PHP框架」第二天:模型与数据库
往期回顾:「七天自制PHP框架」第一天:路由与控制器,点击此处 什么是模型? 我们的WEB系统一定会和各种数据打交道,实际开发过程中,往往一个类对应了关系数据库的一张或多张数据表,这里就会出现两个问题 ...
- 「七天自制PHP框架」第三天:PHP实现的设计模式
往期回顾:「七天自制PHP框架」第二天:模型与数据库,点击此处 原文地址:http://www.cnblogs.com/sweng/p/6624845.html,欢迎关注:编程老头 为什么要使用设计模 ...
- 「七天自制PHP框架」第四天:模型关联
往期回顾:「七天自制PHP框架」第三天:PHP实现的设计模式,点击此处 原文地址:http://www.cnblogs.com/sweng/p/6624845.html,欢迎关注:编程老头 前阵子在网 ...
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- 「拥抱开源, 又见 .NET」系列第三次线下活动简报
「拥抱开源, 又见 .NET」 随着 .NET Core的发布和开源,.NET又重新回到人们的视野. 自2016年 .NET Core 1.0 发布以来,其强大的生命力让越来越多技术爱好者对她的未来满 ...
随机推荐
- centos6.x硬件信息统计脚本
#!/bin/bash Line='===========' #linux发行版名称 if [[ -f /usr/bin/lsb_release ]]; then OS=$(/usr/bin/lsb_ ...
- php mktime()函数
PHP提供一个很好用的函数mktime().你只要按顺序传送给mktime()你希望表示的小时,分钟,秒数,月份,日期,及年份,mktime()就会返回该日期自1970年1月1日的总秒数.获取2000 ...
- html中块元素的居中。及兼容性
块在块中垂直居中(父元素postion:relative; 子元素position:absolute; top:50%; margin-top:负二分之一高度) 块在块中水平居中 (子元素marg ...
- gradle 构建的 Spring Boot 使用 logback
文章讲的是配置和使用,入门请看文档先. what 目的: 可以实现log不同级别的日志记录,例如info 在一个文件夹内,另一个级别的在另一个文件夹内. how 配置依赖项 //log ...
- 05.部分类 partial
namespace _06.部分类 { class Program { static void Main(string[] args) { } } /// <summary> /// 这个 ...
- java TreeSet 实现存自定义不可重复数据
本文主要是介绍一下java集合中的比较重要的Set接口下的可实现类TreeSet TreeSet类,底层用二叉树的数据结构 * 集合中以有序的方式插入和抽取元素. * 添加到TreeSet中的元素必须 ...
- cf1037E. Trips(图论 set)
题意 题目链接 Sol 倒着考虑!倒着考虑!倒着考虑! 显然,一个能成为答案的子图一定满足,其中任意节点的度数\(>= k\) 那么倒着维护就只用考虑删除操作,如果一个点不合法的话就把它删掉,然 ...
- ActiveX界面已显示,调用方法报undefined的处理办法
1.在ie中将当前网址加入信任网站 2.设置->internet选项->安全->受信任站点->自定义级别:将所有有关ActiveX的选项设置为启用 3.重启ie再次访问即可. ...
- 日常捕获的野生知识 - javascript获取屏幕大小
刚刚接触JavaScript,涉及到 document , window 的一些基本知识不是很了解,今天为了一个屏幕大小折腾了半天,幸好找到了很好的例子学习. 代码如下: <html> & ...
- 在oracle表中插入空字段和null测试
create table testTable ( id number, name ) ) select * from testTable ,'user1') ,'') ,null) select co ...