HGOI 20190822 OCWA提高组模拟赛二
Problem A 快递
根节点为$1$ , 含有$n$个节点的树,每一条边都有一段开放的时间$[s_i,e_i]$,和经过需要的时间。
有$q$组询问,每一次在时刻$t_i$出发从根节点出发走到第$u$个节点,沿着最短路走,询问是否可行。
注意到,当在边开放的时间走到这条边上均被认为合法,走出边的时间不会因此而限制。
对于$100\%$的数据,满足$1 \leq n,q \leq 5\times 10^5$
Solution :
考虑能否到达$u$的条件,就是能否在$u$上方的那条边$(fa,u)$的规定时间内到达该点的父亲$fa$。
我们注意到从根节点出发的时间为$time$,那么到达一个节点$u$的总时间就是这个点父亲前缀边的长度之和$pre$。
转化一下,能否到达这个点上方的那一条边的条件就是$time_u + pre \in [s_{Edge} , t_{Edge}]$
解出来就是$time_u \in [s_{Edge}-pre,t_{Edge}-pre]$
所以到达一个点既有当前点的限制,又有该点到根之间点的限制,所以我们只需要将这个点到根的所有点限制的区间交起来就可以了。
这样子,我们直接做一遍$dfs$即可,复杂度就是$O(n+q)$
# pragma GCC optimize()
# include <bits/stdc++.h>
# define inf (1e12)
# define int long long
# define Rint register int
# define YES putchar('Y'),putchar('E'),putchar('S')
# define NO putchar('N'),putchar('O')
using namespace std;
const int N = 5e5+;
struct A { int pre,to,w,s,t; }a[N<<];
struct B { int l,r; }tim[N];
int tot,n,m;
int head[N],d[N],f[N];
inline int read()
{
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
void adde(Rint u,Rint v,int w,int s,int t)
{
a[++tot].pre=head[u];
a[tot].to=v; a[tot].w=w;
a[tot].s=s; a[tot].t=t;
head[u]=tot;
}
void dfs(Rint u,Rint fa)
{
for (Rint i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (v==fa) continue;
tim[v].l=max(tim[u].l,a[i].s-d[u]);
tim[v].r=min(tim[u].r,a[i].t-d[u]);
d[v]=d[u]+a[i].w;
dfs(v,u);
}
}
signed main()
{
n=read();m=read();
for (Rint i=;i<=n;i++) {
int u=read()+,v=read()+,w=read(),s=read(),t=read();
adde(u,v,w,s,t); adde(v,u,w,s,t);
}
tim[].l=-inf; tim[].r=inf;
dfs(,);
while (m--) {
int u=read()+,t=read();
(t>=tim[u].l && t<=tim[u].r)?(YES):(NO);
putchar('\n');
}
return ;
}
A.cpp
Problem B 工资
给出一个$1$为根节点,含有$n$个节点的树,每个点初始有一个权值$v_i$。
维护两种操作,"u A x" 表示将编号为$A$的子树除了节点$A$的所有节点权值加$x$,"p A"表示求编号为$A$节点的权值。
对于$100\%$的数据满足$1 \leq n,q \leq 5\times 10^5$
Solution :
由于子树的$dfs$序是连续的,所以本题直接按照dfs序建立树状数组即可。
维护区间加,单点求和。
复杂度是$O((q+n) log_2 n)$
# pragma GCC optimize()
# include <bits/stdc++.h>
# define int long long
# define Rint int
using namespace std;
const int N=5e5+;
struct rec{
int pre,to;
}a[N<<];
int c[N],head[N],dfn[N],R[N],val[N];
int tot,n,m;
# define lowbit(x) (x&(-x))
void update(int x,int y){for (;x<=n;x+=lowbit(x)) c[x]+=y;}
int query(int x) { int ret=; for (;x;x-=lowbit(x)) ret+=c[x];return ret;}
int modify(int l,int r,int d) {update(l,d); update(r+,-d);}
#undef lowbit
inline int read()
{
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
void write(int x)
{
if (x<) x=-x,putchar('-');
if (x>) write(x/);
putchar(''+x%);
}
inline void writeln(int x) {
write(x); putchar('\n');
}
inline void adde(Rint u,Rint v)
{
a[++tot].pre=head[u];
a[tot].to=v;
head[u]=tot;
}
void dfs(Rint u,Rint fa)
{
dfn[u]=++dfn[]; R[u]=dfn[u];
for (Rint i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (v==fa) continue;
dfs(v,u);
}
R[u]=dfn[];
}
signed main()
{
n=read(); m=read(); val[]=read();
for (Rint i=;i<=n;i++) {
int f; val[i]=read(); f=read();
adde(i,f); adde(f,i);
}
for (int i=;i<=n;i++) if (!dfn[i]) dfs(i,);
for (Rint i=;i<=n;i++) modify(dfn[i],dfn[i],val[i]);
while (m--) {
char c=; while (c!='p' && c!='u') c=getchar();
if (c=='u') {
int x=read();
writeln(query(dfn[x]));
}else {
int x=read(),y=read();
if (dfn[x]+<=R[x]) modify(dfn[x]+,R[x],y);
}
}
return ;
}
B.cpp
Problem C 坤坤数
坤坤数的定义是:对于一个数,不含前导零,给定$k$,存在$wk ,w \geq 1$作为后缀的数。
现在,我们给出$n$,$k$和$m$,求出$n$位坤坤数的数的个数$mod \ m$的值。
对于$100\%$的数据满足$n \leq 1000 ,1 \leq k \leq 100 , 1 \leq m \leq 10^9$
Solution :
考虑$f[i][j][0/1][0/1]$表示当前考虑到第$i$位,当前数$mod \ k$为$j$,是否含有前导零,是否之前的后缀已经是$wk$了(即是否已经构成)
设从第$0$位开始添加数,那么最后的答案就是$\sum\limits_{i = 0}^{k-1} f[n-1][i][0][1]$ 。
考虑刷表法转移,
- $f[i][j][0][0] -> f[i+1][j][1][0] , f[i+1][(w\times 10^{i+1}+j)\% k][0][0]((w\times 10^{i+1}+j)\% k \neq 0) , f[i+1][0][0][1]$
- $f[i][j][0][1] -> f[i+1][j][1][1] , f[i+1][(w\times 10^{i+1}+j)\% k][0][1]$
- $f[i][j][1][0] -> f[i+1][j][1][0] , f[i+1][(w\times 10^{i+1}+j)\% k][0][0]((w\times 10^{i+1}+j)\% k \neq 0) , f[i+1][0][0][1]$
- $f[i][j][1][1] -> f[i+1][j][1][1] , f[i+1][(w\times 10^{i+1}+j)\% k][0][1]$
我们可以预处理出幂次取模,那么最后的复杂度就是$O(10 \times n \times k)$
#pragma GCC optimize(3)
# include <bits/stdc++.h>
# define int long long
using namespace std;
int n,k,m;
int f[][][][];
int Pow(int x,int n,int mo)
{
int ans=;
while (n) {
if (n&) ans=ans*x%mo;
x=x*x%mo;
n>>=;
}
return ans%mo;
}
signed main()
{
scanf("%lld%lld%lld",&n,&k,&m);
(f[][][][]+=)%=m;
for (int i=;i<=;i++) {
bool ok = ;
for (int w=;w<=;w++) {
if (w*k>) break;
if (w*k==i) { (f[][i%k][][]+=)%=m; ok = ; break;}
}
if (!ok) (f[][i%k][][]+=)%=m;
}
for (int i=;i<=n-;i++)
for (int j=;j<=k-;j++) {
(f[i+][j][][]+=f[i][j][][])%=m;
for (int w=;w<=;w++)
if ((w*Pow(,i+,k)%k+j)%k==) (f[i+][][][]+=f[i][j][][])%=m;
else (f[i+][(w*Pow(,i+,k)%k+j)%k][][]+=f[i][j][][])%=m; (f[i+][j][][]+=f[i][j][][])%=m;
for (int w=;w<=;w++)
(f[i+][(w*Pow(,i+,k)%k+j)%k][][]+=f[i][j][][])%=m; (f[i+][j][][]+=f[i][j][][])%=m;
for (int w=;w<=;w++)
if ((w*Pow(,i+,k)%k+j)%k==) (f[i+][][][]+=f[i][j][][])%=m;
else (f[i+][(w*Pow(,i+,k)%k+j)%k][][]+=f[i][j][][])%=m; (f[i+][j][][]+=f[i][j][][])%=m;
for (int w=;w<=;w++)
(f[i+][(w*Pow(,i+,k)%k+j)%k][][]+=f[i][j][][])%=m;
}
int ret = ;
for (int i=;i<=k-;i++) (ret+=f[n-][i][][])%=m;
printf("%lld\n",ret);
return ;
}
C.cpp
HGOI 20190822 OCWA提高组模拟赛二的更多相关文章
- OCWA提高组模拟赛一 Solution
Problem A RecMin 给出一个$n \times m$的矩阵,其中$1 \leq n,m \leq 3\ times 10^3$ 给出整数$a,b$,求出在矩阵中所有$a\ times b ...
- NOIP2017提高组模拟赛 8(总结)
NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...
- NOIP2017提高组模拟赛 7(总结)
NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...
- NOIP2017提高组模拟赛5 (总结)
NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...
- ZROI提高组模拟赛05总结
ZROI提高组模拟赛05总结 感觉是目前为止最简单的模拟赛了吧 但是依旧不尽人意... T1 有一半的人在30min前就A掉了 而我花了1h11min 就是一个简单的背包,我硬是转化了模型想了好久,生 ...
- NOIP2017提高组 模拟赛15(总结)
NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...
- NOIP2017提高组 模拟赛13(总结)
NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...
- NOIP2017提高组模拟赛 10 (总结)
NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...
- NOIP2017提高组模拟赛 9 (总结)
NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...
随机推荐
- Makefile 书写规则
1.1 Makefile的规则 在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则. target ... : prerequisites ... command ...
- 谷歌官方颜色库 MaterialDesignColor
谷歌官方颜色库 MaterialDesignColor
- Keras模型训练的断点续训、早停、效果可视化
训练:model.fit()函数 fit(x=None, y=None, batch_size=None, epochs=, verbose=, callbacks=None, validation_ ...
- 如何决定使用 HashMap 还是 TreeMap? (转)
问:如何决定使用 HashMap 还是 TreeMap? 介绍 TreeMap<K,V>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照 ...
- node工具之node-ip
node-ip node.js用来获取id地址的工具 use var ip = require('ip'); ip.address() // my ip address ip.isEqual('::1 ...
- ajax实现异步操作实例1
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 权限(rwx)对于目录与文件的意义
1-权限对于目录的意义 首先要明白的是目录主要的内容是记录文件名列表和子目录列表,而不是实际存放数据的地方. r权限:拥有此权限表示可以读取目录结构列表,也就是说可以查看目录下的文件名和子目录名,注意 ...
- 移动端布局-rem
created(){ // 设置根字号 // 屏幕宽度 setHTML(); // addEventListener()不冲突 window.addEventListener('resize', se ...
- Red Hat Enterprise Linux 6安装好,开启网卡到搭建tftp服务器和安装dnw驱动,安装samba服务器
今天一顿误操作,只能把Red Hat Enterprise Linux 6重新安装,一些必备工作只能重做,重做之后立马把Linux的文件备份,以备不时只需! 开启Linux以太网卡:vim /etc/ ...
- SAP中MM模块基础数据之Quota Arrangement(配额协议)的解析
有的时候我们的采购部门有这样的需求, 同一颗物料有几个供应商同时供料, 这个时候就涉及到一个问题, 避免出现总是和一家供应商购买物料的情况,我们需求把这些物料按照一定的比列分配给供应商.在SAP系统中 ...