「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 发布以来,其强大的生命力让越来越多技术爱好者对她的未来满 ...
随机推荐
- [转]Consuming a OData Service in a Client Application (WCF Data Services)
本文转自:https://msdn.microsoft.com/zh-tw/library/dd728282(v=vs.103).aspx WCF Data Services 5.0 其他版本 ...
- [转]用Excel制作甘特图并管理项目
对于比较简单的项目管理,或绘制甘特图,选用电子表格工具——比如价格高也最强大的Excel.开源的OpenOffice.免费的WPS——可能比项目管理软件更方便. 1. XL-Easy Gantt 模板 ...
- JMS - ActiveMQ的简单使用
首先需要下载ActiveMQ,下面的链接给我们列出了所有版本:http://activemq.apache.org/download-archives.html每个版本为不同的OS提供了链接: 公司电 ...
- Cheatsheet: 2017 04.01 ~ 04.30
Other ReactXP - A LIBRARY FOR BUILDING CROSS-PLATFORM APPS Merging vs. Rebasing Better Git configura ...
- HTML DOM status 属性
<!DOCTYPE html><html> <head>HTML DOM status 属性</head><body><script ...
- js上传并且预览图片
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Idea创建Hibernate bean类和.xml文件
Idea通过表结构反向生成Hibernate实体类和映射文件 首先:之前通过Eclipse反向生成Hibernate的实体类,很傻瓜式,基本上不用配置.但是Idea通过表结构反向生成hibernate ...
- javascript运算符之==和===
1.== :判断两个数是否相等,在比较之前会自动转化类型再做比较.为确定两个运算数是否相等,这两个运算符都会进行类型转换. 执行类型转换的规则如下: 1.如果一个运算数是 Boolean 值,在检查相 ...
- js 两个小括号 ()() 的用法
实现一个函数fn, 使fn(1)(2)的结果为两个参数的和,刚开始没反应过来,其实细细一想第二个括号就是函数再调用的问题,废话不多说,代码奉上: var fn = function(n) { func ...
- jquery根据id取不到textarea对象,无法给textarea赋值
小编定义了一个textarea控件,却无法根据id取到textarea对象并赋值. 经过实验,得出了原因.代码如下: <!DOCTYPE html><html><head ...