题解:CSP-S2020] 函数调用
题解:CSP-S2020] 函数调用
一句话题意:给定一个有初始值的序列,支持如下三种操作:
- 1、单点加
- 2、全局乘
- 3、递归某些操作1、2、3
求最终的序列。
标签:topsort,动态规划,转化贡献统计(集中贡献),主客翻转
关于topsort:部分分里的树结构基本上直接暗示了正解要使用topsort,而且本来函数关系就会组成一张DAG。
关于贡献转化:
- 加、乘运算的独立比较容易想到:即某个元素的终值=初值*全局乘因子+扩倍后每个加法因子
- 简单来说,
- 加、乘运算的独立比较容易想到:即某个元素的终值=初值*全局乘因子+扩倍后每个加法因子
\]
感觉难点在于想到贡献的统计要全部转化到操作1上
如果针对每个操作统计贡献,那意味着每个操作上要挂原序列中的 \(n\) 个数,显然不管是空间还是时间,这都是无法承受的。而我们可以通过动态规划的方式将所有贡献转到操作1上。(搞了半天精髓还是在动规上!!!)
- 全局乘因子可以一遍倒序topsort求得
- 扩倍后每个加法因子可以一遍正序top求得,思想见这篇博客
- 简单来说就是同父亲的儿子的乘法因子受到更靠右的儿子的影响,链式前向星的遍历顺序天然地满足我们从右到左遍历儿子的需求。
- 最后合并贡献
a[b[i].p]=((a[b[i].p]+1ll*b[i].v*b[i].sum)%mod+mod)%mod;(存疑:为何还要乘
b[i].v???sum中没有包含吗?)
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
char buf[100],*p1=buf,*p2=buf;
inline int gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++;}
inline int rd(){
int x=0; char ch;
while(!isdigit(ch=gc()));
do x=(x<<3)+(x<<1)+(ch^48); while(isdigit(ch=gc()));
return x;
}
const int N=1e6+5;
const int mod=998244353;
struct node{
int op,p,v,mul,sum;
}b[N];
struct edge{
int v,ne;
}e[N<<1];
int n,m,q,idx=0,cnt=0;
int in[N],a[N],first[N],ord[N],f[N];
void add(int x,int y){e[++idx]=(edge){y,first[x]};first[x]=idx;}
void topsort(){
queue<int> q;
F(i,1,m) if(!in[i]) q.emplace(i);
while(q.size()){
int u=q.front(); q.pop();
ord[++cnt]=u;
for(int i=first[u];i;i=e[i].ne){
int v=e[i].v;
if(!(--in[v])) q.emplace(v);
}
}
}
void getmul(){
G(o,m,1){
int u=ord[o];
for(int i=first[u];i;i=e[i].ne){
int v=e[i].v;
b[u].mul=(1ll*b[u].mul*b[v].mul)%mod;
// nw=(1ll*nw*b[u].mul)%mod;
}
}
}
void getsum(){
F(o,1,m){
int u=ord[o],nw=1;
for(int i=first[u];i;i=e[i].ne){
int v=e[i].v;
b[v].sum=(1ll*b[v].sum+1ll*nw*b[u].sum)%mod;
nw=(1ll*nw*b[v].mul)%mod;
}
}
}
signed main(){
n=rd();
F(i,1,n) a[i]=rd();
m=rd();
F(i,1,m){
b[i].op=rd();
if(b[i].op==1){
b[i].p=rd(),b[i].v=rd();
b[i].mul=1;
}
else if(b[i].op==2){
b[i].v=rd();
b[i].mul=b[i].v;
}
else{
b[i].p=rd();
b[i].mul=1;
F(j,1,b[i].p){
int o=rd();
add(i,o);
in[o]++;
}
}
}
topsort();
getmul();
q=rd(); int nw=1;
F(i,1,q) f[i]=rd();
G(i,q,1){
int x=f[i];
b[x].sum=(b[x].sum+1ll*nw)%mod;
nw=(1ll*nw*b[x].mul)%mod;
}
getsum();
F(i,1,n) a[i]=(1ll*a[i]*nw)%mod;
F(i,1,m){
if(b[i].op==1){
a[b[i].p]=((a[b[i].p]+1ll*b[i].v*b[i].sum)%mod+mod)%mod;
}
}
F(i,1,n) printf("%d ",a[i]);
return 0;
}
- 总结:答案贡献分散,难以统计时,考虑转化统计主体,以集中贡献,优化算法。
题解:CSP-S2020] 函数调用的更多相关文章
- [CSP-S 2019 day2 T2] 划分
题面 题解 CSP赛场上能请教别人吗 在这道题中,我看到了一个很敏感又很熟悉的东西--平方! 这意味着,可以推出一些结论,使这道题几乎可以边输入边解决. 自己在脑子里动态一下就知道,像这种总和一定.代 ...
- 2019 CSP J/S第2轮 视频与题解
CSP入门组和提高组第二轮题解 转自网络
- 上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解
前 言: 一直很想写这道括号树..毕竟是在去年折磨了我4个小时的题.... 上午小测3 T1 括号序列 前言: 原来这题是个dp啊...这几天出了好几道dp,我都没看出来,我竟然折磨菜. 考试的时候先 ...
- [CSP模拟测试43、44]题解
状态极差的两场.感觉现在自己的思维方式很是有问题. (但愿今天考试开始的一刻我不会看到H I J) A 考场上打了最短路+贪心,水了60. 然而正解其实比那30分贪心好想多了. 进行n次乘法后的结果一 ...
- 题解 nflsoj489 【六校联合训练 CSP #15】小D与随机
题目链接 考虑枚举好点的集合.此时要考虑的问题是如何填入\(1\sim n\)这些数使得恰好我们枚举到的这些点是好点,即:求出有多少种合法的填数方案. \(1\)号点一定是好点.那么除\(1\)号点外 ...
- C++对象模型的那些事儿之六:成员函数调用方式
前言 C++的成员函数分为静态函数.非静态函数和虚函数三种,在本系列文章中,多处提到static和non-static不影响对象占用的内存,而虚函数需要引入虚指针,所以需要调整对象的内存布局.既然已经 ...
- CSP应用开发-CryptAPI函数库介绍
基本加密函数为开发加密应用程序提供了足够灵活的空间.所有CSP的通讯都是通过这些函数.一个CSP是实现所有加密操作的独立模块.在每一个应用程序中至少需要提供一个CSP来完成所需的加密操作.如果使用多于 ...
- 算法(第四版)C# 习题题解——2.3
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更为方便的版本见:http ...
- CCF CSP 201703-3 Markdown
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-3 Markdown 问题描述 Markdown 是一种很流行的轻量级标记语言(l ...
- CCF计算机职业资格认证考试题解
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF计算机职业资格认证考试题解 CCF计算机软件能力认证(简称CCF CSP认证)是CCF计算机职业资格认证系 ...
随机推荐
- 使用 defineNuxtRouteMiddleware 创建路由中间件
title: 使用 defineNuxtRouteMiddleware 创建路由中间件 date: 2024/8/10 updated: 2024/8/10 author: cmdragon exce ...
- vue中使用better-scroll
1.创建vue-cli3项目 指令 vue create 项目名 2.要想使用better-scroll 需要先引入 better-scroll的插件 这里采用 npm的方式 指令 npm ...
- 聊一聊 C# 中让人惶恐的 Bitmap
一:背景 1. 讲故事 在.NET高级调试的旅程中,我常常会与 Bitmap 短兵相接,它最大的一个危害就是会让程序抛出匪夷所思的 OutOfMemoryException,也常常会让一些.NET开发 ...
- CSEC:香港城市大学提出SOTA曝光矫正算法 | CVPR 2024
在光照条件不佳下捕获的图像可能同时包含过曝和欠曝.目前的方法主要集中在调整图像亮度上,这可能会加剧欠曝区域的色调失真,并且无法恢复过曝区域的准确颜色.论文提出通过学习估计和校正这种色调偏移,来增强既有 ...
- macOS 扫描局域网设备
arp-scan: arp-scan 是一个直接用于扫描本地网络中的设备的 UNIX 工具.这不是 macOS 自带的,但可以使用 Homebrew 安装.首先安装 Homebrew(如果尚未安装), ...
- Redis过期策略以及Redis的内存淘汰机制
此篇介绍了Redis过期策略以及Redis的内存淘汰机制,从内存淘汰的8种策略,如何开启内存淘汰策略到如何选择合适的淘汰策略,对Redis的内存淘汰机制做了全方位的阐述 如何高效的使用内存对于redi ...
- 多表查询 —— 内连接&外连接&子查询
连接查询 内连接 1.查询语法 -- 隐式内连接 select 字段列表 from 表1, 表2... where 条件; -- 显式内连接 select 字段列表 from 表1 [INNER] j ...
- docker基础镜像java版本选择和推荐
背景 在编写dockerfile时,基础镜像要么太大,要么缺少jdk:dockerhub中的openjdk五花八门,不知道选择哪个 解决方案 我在项目中通常选择 openjdk作为基础镜像 FROM ...
- Project: Kill e
接到上级任务,今天来暗杀 \(e\) 据说杀死 \(e\) 的方式就是把他算出来,好吧,现在我们还是来算一下 考虑使用如下代数式求解 \[e\ \text{site:baidu.com} \] 虽然我 ...
- 将python文件编译成exe文件
第一种方法:我们只会生成一个exe文件,因为所有的库文件他都会包含在这个exe文件中 1.安装:pyinstaller pip install pyinstaller 2.使用如下命令编译 pyins ...