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)颗星的矩形的最小面 ...
随机推荐
- 摘抄大神对VUE 中slot-scope的深度理解
Vue的slot-scope的场景的个人理解 这篇文章不是单纯把文档的话和api拿来翻译和演示,而是谈谈我对于slot-scope的使用场景的个人理解,如果理解错误,欢迎讨论! Vue的插槽slot, ...
- JAVA二维码编码&解码
QRCodeUtil.java package web; import java.awt.AlphaComposite; import java.awt.Color; import java.awt. ...
- Python-RabbitMQ-fanout(广播模式)
生产者:fanout_publiser.py import pika import sys connection = pika.BlockingConnection(pika.ConnectionPa ...
- python-queue队列-生产者消费者
import threading,time import queue q = queue.Queue(maxsize=10) def Producer(name):#生产者 count=1 while ...
- python内置函数简单归纳
做python小项目的时候发现熟练运用python内置函数,可以节省很多的时间,在这里整理一下,便于以后学习或者工作的时候查看.函数的参数可以在pycharm中ctrl+p查看. 1.abs(x):返 ...
- Linux Exploit系列之二 整数溢出
整数溢出 虚拟机安装:Ubuntu 12.04(x86) 什么是整数溢出? 存储大于最大支持值的值称为整数溢出.整数溢出本身不会导致任意代码执行,但整数溢出可能会导致堆栈溢出或堆溢出,这可能导致任意代 ...
- Java高并发程序设计学习笔记(一):并行简介以及重要概念
转自:https://blog.csdn.net/dataiyangu/article/details/86211544#_28 文章目录为什么需要并行?反对意见大势所趋几个重要的概念同步(synch ...
- 工作中apache 403的一个小问题
最近在虚拟机上安装hadoop, 需要设备本地的网络源,所以启用了apache. 由于需要,首先修改了家目录的位置 指向/opt/www 然后修改家目录的配置文件 修改完成之后重启服务,访问目录 ...
- VMware安装CentOS6.3
这里测试的是 CentOS-6.3-x86_64-bin-DVD1 链接:点击进入提取码: zs32 如果这里CentOS下载太慢的话 点击进入下载
- facenet pyhton3.5 训练 train_softmax.py 时报错AttributeError: 'dict' object has no attribute 'iteritems'
报错原因:在进行facenet进行train_softmax.py训练时,在一轮训练结束进行验证时,报错AttributeError: 'dict' object has no attribute ' ...