Solution -「CSP-S 2020」函数调用
Description
大家应该都读过题。
Solution
赛后变摩托。
我们对每一个操作 \(3\) 连边建图,然后可以知道只是一个 \(\texttt{DAG}\)。
考虑操作 \(2\),我们只需要最后计算即可。
现在来看加法操作。我们设我们当前的操作为 \(a_{p}\leftarrow a_{p}+v\),后面一共有 \(k\) 个乘法操作,我们设为分别让序列整体乘上 \(b_{1,2,\cdots,k}\)。那么 \(a_{p}\leftarrow a_{p}+v\) 一共会对最后的 \(a_{p}\) 产生 \(v\times\prod_{i=1}^{k}b_{i}\) 的贡献。
于是我们可以把操作离线下来,倒着来处理。
那么最后来考虑操作 \(3\),我们来看操作 \(3\) 连出的图。
对于图上的每一个节点我们维护一个值,表示执行后会带来的系数。
那么和操作 \(1\) 类似的,我们对整张图进行拓扑,然后倒着处理,处理出每个节点的操作的加法计算了多少次,然后传播(指所有相邻节点)到加法操作的节点。
最后处理原序列即可。
(代码从 \(\texttt{Vim}\) 里面复制出来可能缩进有问题)
#include <queue>
#include <cstdio>
#define mod ( 998244353 )
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 5;
template<typename _T>
void read( _T &x ){
x = 0; char c = getchar(); _T f = 1;
while( c < '0' || c > '9' ){ if( c == '-' ) f = -1; c = getchar(); }
while( c >= '0' && c <= '9' ){ x = ( x << 3 ) + ( x << 1 ) + ( c & 15 ); c = getchar(); }
x *= f;
}
template<typename _T>
void write( _T x ){
if( x < 0 ){ putchar( '-' ); x = -x; }
if( x > 9 ) write( x / 10 );
putchar( x % 10 + '0' );
}
struct starS{
int to, nxt;
starS( int T = 0, int N = 0 ){ to = T; nxt = N; }
} as[MAXN * 2];
struct operateS{
int Tp, pos;
LL add, mul, sum;
operateS( int T = 0, int P = 0, LL A = 0, LL M = 0, LL S = 0 ){ Tp = T; pos = P; add = A; mul = M; sum = S; }
} opS[MAXN];
int N, M, Q;
int totE, totT;
int A[MAXN], topS[MAXN], degS[MAXN], firS[MAXN], queS[MAXN];
void pushEdge( int u, int v ){ as[++ totE] = starS( v, firS[u] ); firS[u] = totE; }
void TopSort( ){
queue<int> align;
for( int i = 1; i <= M; ++ i ){
if( ! degS[i] ) align.push( i );
}
while( ! align.empty( ) ){
int u = align.front( ); align.pop( );
topS[++ totT] = u;
for( int i = firS[u]; i; i = as[i].nxt ){
int v = as[i].to; degS[v] --;
if( ! degS[v] ) align.push( v );
}
}
}
int main( ){
read( N );
for( int i = 1; i <= N; ++ i ) read( A[i] );
read( M );
for( int i = 1; i <= M; ++ i ){
read( opS[i].Tp );
if( opS[i].Tp == 1 ){
read( opS[i].pos ); read( opS[i].add );
opS[i].mul = 1;
}
else if( opS[i].Tp == 2 ) {
read( opS[i].mul );
opS[i].add = opS[i].mul;
}
else{
read( opS[i].pos );
opS[i].mul = 1;
for( int j = 1, to; j <= opS[i].pos; ++ j ){ read( to ); pushEdge( i, to ); degS[to] ++; }
}
}
TopSort( );
for( int i = M; i; -- i ){
int u = topS[i];
for( int j = firS[u]; j; j = as[j].nxt ){
int v = as[j].to;
opS[u].mul = ( LL )opS[u].mul * opS[v].mul % mod;
}
}
read( Q ); int now = 1;
for( int i = 1; i <= Q; ++ i ) read( queS[i] );
for( int i = Q; i; -- i ){ opS[queS[i]].sum = ( ( LL )opS[queS[i]].sum + now ) % mod; now = ( LL )now * opS[queS[i]].mul % mod; }
for( int i = 1; i <= M; ++ i ){
int u = topS[i], now = 1;
for( int j = firS[u]; j; j = as[j].nxt ){
int v = as[j].to;
opS[v].sum = ( ( LL )opS[u].sum * now % mod + opS[v].sum ) % mod;
now = ( LL )now * opS[v].mul % mod;
}
}
for( int i = 1; i <= N; ++ i ) A[i] = ( LL )A[i] * now % mod;
for( int i = 1; i <= M; ++ i ){
if( opS[i].Tp == 1 ) A[opS[i].pos] = ( A[opS[i].pos] + ( LL )opS[i].add * opS[i].sum % mod ) % mod;
}
for( int i = 1; i <= N; ++ i ) write( A[i] ), putchar( ' ' );
return 0;
}
Solution -「CSP-S 2020」函数调用的更多相关文章
- Solution -「多校联训」排水系统
\(\mathcal{Description}\) Link. 在 NOIP 2020 A 的基础上,每条边赋权值 \(a_i\),随机恰好一条边断掉,第 \(i\) 条段的概率正比于 \(a ...
- Note/Solution -「洛谷 P5158」「模板」多项式快速插值
\(\mathcal{Description}\) Link. 给定 \(n\) 个点 \((x_i,y_i)\),求一个不超过 \(n-1\) 次的多项式 \(f(x)\),使得 \(f(x ...
- Solution -「洛谷 P4198」楼房重建
\(\mathcal{Description}\) Link. 给定点集 \(\{P_n\}\),\(P_i=(i,h_i)\),\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后 ...
- Solution -「洛谷 P6577」「模板」二分图最大权完美匹配
\(\mathcal{Description}\) Link. 给定二分图 \(G=(V=X\cup Y,E)\),\(|X|=|Y|=n\),边 \((u,v)\in E\) 有权 \(w( ...
- Solution -「多校联训」I Love Random
\(\mathcal{Description}\) 给定排列 \(\{p_n\}\),可以在其上进行若干次操作,每次选取 \([l,r]\),把其中所有元素变为原区间最小值,求能够得到的所有不同序 ...
- Solution -「多校联训」签到题
\(\mathcal{Description}\) Link. 给定二分图 \(G=(X\cup Y,E)\),求对于边的一个染色 \(f:E\rightarrow\{1,2,\dots,c\ ...
- Solution -「多校联训」朝鲜时蔬
\(\mathcal{Description}\) Link. 破案了,朝鲜时蔬 = 超现实树!(指写得像那什么一样的题面. 对于整数集 \(X\),定义其 好子集 为满足 \(Y\sub ...
- Solution -「多校联训」消失的运算符
\(\mathcal{Description}\) Link. 给定长度为 \(n\) 的合法表达式序列 \(s\),其中数字仅有一位正数,运算符仅有 - 作为占位.求将其中恰好 \(k\) ...
- Solution -「多校联训」假人
\(\mathcal{Description}\) Link. 一种物品有 长度 和 权值 两种属性,现给定 \(n\) 组物品,第 \(i\) 组有 \(k_i\) 个,分别为 \((1,a ...
- Solution -「多校联训」古老的序列问题
\(\mathcal{Description}\) Link. 给定序列 \(\{a_n\}\),和 \(q\) 次形如 \([L,R]\) 的询问,每次回答 \[\sum_{[l,r]\su ...
随机推荐
- 可视化生信分析利器 Galaxy 之 Docker 开发
1. 背景 我们常常会基于某个 image 来启动一个 container,在这个 container 中我们可能会执行某些操作,比如创建一个文件,但是当这个 container 退出以后,如果我们以 ...
- 安卓第一课:gradle仓库的导入
今天装好android studio,结果刚进入就报错了: SSL peer shut down incorrectly 读注释发现原来是gradle下载文件不成功.果然,原来是vpn掉线了,上网查了 ...
- CMU15445 (Fall 2020) 之 Project#1 - Buffer Pool 详解
前言 去年暑假完成了 CMU15-445 Fall 2019 的四个实验,分别对应下述博客: CMU15445 (Fall 2019) 之 Project#1 - Buffer Pool 详解 CMU ...
- 体验昇腾Ascend C 编程语言极简易用的算子开发
摘要:昇腾Ascend C编程语言,让基于昇腾AI的算法创新更加简单. 本文分享自华为云社区<CANN黑科技解密|昇腾Ascend C编程语言 - 极简易用的算子开发体验>,作者:昇腾CA ...
- 前端vue单个文件上传支持图片,压缩包以及文件 , 下载完整代码请访问uni-app插件市场址:https://ext.dcloud.net.cn/plugin?id=13066
前端vue单个文件上传支持图片,压缩包以及文件 , 下载完整代码请访问uni-app插件市场址:https://ext.dcloud.net.cn/plugin?id=13066 效果图如下: 使用方 ...
- PostgreSQL 12 文档: 部分 VI. 参考
部分 VI. 参考 这份参考中的条目意欲提供关于相应主题的权威.完整和正式的总结.关于使用PostgreSQL的更多信息(以叙述.教程或例子的形式)可以在本书的其他部分找到.见每个参考页面上列出的交叉 ...
- 记一次 .NET 某游戏服务后端 内存暴涨分析
一:背景 1. 讲故事 前几天有位朋友找到我,说他们公司的后端服务内存暴涨,而且CPU的一个核也被打满,让我帮忙看下怎么回事,一般来说内存暴涨的问题都比较好解决,就让朋友抓一个 dump 丢过来,接下 ...
- 关于 Task 简单梳理
〇.前言 Task 是微软在 .Net 4.0 时代推出来的,也是微软极力推荐的一种多线程的处理方式. 在 Task 之前有一个高效多线程操作累 ThreadPool,虽然线程池相对于 Thread, ...
- Centos查看挂载目录并挂载
一.概述 本次已Centos7作为示例 挂载系统没有挂载的磁盘,可以分如下几步 1.查看系统哪些盘未挂载 2.给未挂载的磁盘进行分区 3.格式化磁盘并向磁盘中写入系统文件 4.挂载磁盘 5.设置开机自 ...
- 《深入理解Java虚拟机》读书笔记:判断对象是否存活
本节内容的概要如下; 对象已死吗? 一.判断对象是否存活的算法 1.引用计数器算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0 ...