题解:AT_abc357_f [ABC357F] Two Sequence Queries
题意
维护一个数据结构,支持两个数列的区间求和,和查询区间内两数列各元素积的和。
分析
线段树万岁!
这道题要维护两个序列,所以线段树中要同时存储两个区间和。但还要在维护一个信息,是该区间内两序列元素积的和。大概长这样:
struct no
{
int l,r;
int da,db,ab;
int ta,tb;
}t[maxn<<2];
其他的更新就不讲了,主要说一说积的和信息的更新。
当更新一个序列时,该信息要传递的信息其实是另一盒序列的和乘上该序列的懒标记,这点很好想。
然后就没有什么问题了。但是注意这道题要取模,你少取一个就废了。
Code
#include<bits/stdc++.h>
//#include<atcoder/modint>
#define int long long
using namespace std;
//using mint=atcoder::modint998244353;
inline int read()
{
int w=1,s=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
return w*s;
}
const int maxn=1e6+10;
const int mod=998244353;
struct no
{
int l,r;
int da,db,ab;
int ta,tb;
}t[maxn<<2];
int a[maxn],b[maxn],n,Q;
void upd(int p)
{
t[p].da=(t[p*2].da+t[p*2+1].da)%mod;
t[p].db=(t[p*2].db+t[p*2+1].db)%mod;
t[p].ab=(t[p*2].ab+t[p*2+1].ab)%mod;
}
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r)
{
t[p].da=a[l]%mod;t[p].db=b[l]%mod;
t[p].ab=a[l]*b[l]%mod;
return ;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
upd(p);
}
void spread(int p)
{
if(t[p].ta)
{
t[p*2].da+=t[p].ta*(t[p*2].r-t[p*2].l+1)%mod;t[p*2].da%=mod;
t[p*2+1].da+=t[p].ta*(t[1+p*2].r-t[1+p*2].l+1)%mod;t[p*2+1].da%=mod;
t[p*2].ta+=t[p].ta;t[p*2].ta%=mod;
t[p*2+1].ta+=t[p].ta;t[p*2+1].ta%=mod;
t[p*2].ab+=t[p].ta*t[p*2].db%mod;t[p*2].ab%=mod;
t[p*2+1].ab+=t[p].ta*t[p*2+1].db%mod;t[p*2+1].ab%=mod;
}
if(t[p].tb)
{
t[p*2].db+=t[p].tb*(t[p*2].r-t[p*2].l+1)%mod;t[p*2].db%=mod;
t[p*2+1].db+=t[p].tb*(t[1+p*2].r-t[1+p*2].l+1)%mod;t[p*2+1].db%=mod;
t[p*2].tb+=t[p].tb;t[p*2].tb%=mod;
t[p*2+1].tb+=t[p].tb;t[p*2+1].tb%=mod;
t[p*2].ab+=t[p].tb*t[p*2].da%mod;t[p*2].ab%=mod;
t[p*2+1].ab+=t[p].tb*t[p*2+1].da%mod;t[p*2+1].ab%=mod;
}
t[p].ta=0;
t[p].tb=0;
}
void changea(int p,int l,int r,int k)
{
if(t[p].l>=l&&t[p].r<=r)
{
t[p].da+=k*(t[p].r-t[p].l+1)%mod;t[p].da%=mod;
t[p].ta+=k;t[p].ta%=mod;
t[p].ab+=k*t[p].db%mod;t[p].ab%=mod;
return ;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)changea(p*2,l,r,k);
if(mid<r) changea(p*2+1,l,r,k);
upd(p);
}
void changeb(int p,int l,int r,int k)
{
if(t[p].l>=l&&t[p].r<=r)
{
t[p].db+=k*(t[p].r-t[p].l+1)%mod;t[p].db%=mod;
t[p].tb+=k;t[p].tb%=mod;
t[p].ab+=k*t[p].da%mod;t[p].ab%=mod;
return ;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)changeb(p*2,l,r,k);
if(mid<r) changeb(p*2+1,l,r,k);
upd(p);
}
int ask(int p,int l,int r)
{
if(t[p].l>=l&&t[p].r<=r)
{
return t[p].ab%mod;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1,sum=0;
if(l<=mid)sum=(sum+ask(p*2,l,r)%mod)%mod;
if(mid<r) sum=(sum+ask(p*2+1,l,r)%mod)%mod;
return sum%mod;
}
signed main()
{
// freopen("xxx.in","r",stdin);
// freopen("xxx.out","w",stdout);
cin>>n>>Q;
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
build(1,1,n);
while(Q--)
{
int opt=read(),l=read(),r=read();
if(opt==3)
{
printf("%lld\n",ask(1,l,r)%mod);
continue;
}
int x=read();
if(opt==1)changea(1,l,r,x);
if(opt==2)changeb(1,l,r,x);
}
return 0;
}
题解:AT_abc357_f [ABC357F] Two Sequence Queries的更多相关文章
- 【题解】Cut the Sequence(贪心区间覆盖)
[题解]Cut the Sequence(贪心区间覆盖) POJ - 3017 题意: 给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量. 题解 考虑一个这样的贪心: 先按照左端 ...
- 题解 CF1304E 【1-Trees and Queries】
前言 这场比赛,在最后 \(5\) 分钟,我想到了这道题的 \(Idea\),但是,没有打完,比赛就结束了. 正文 题目意思 这道题目的意思就是说,一棵树上每次给 \(x\) 和 \(y\) 节点连 ...
- 【题解】Luogu CF817F MEX Queries
原题传送门 817,我突然想到了某8位质数 这题珂以说是珂朵莉树的模板 三个操作都肥肠简单,前两个区间赋值,第三个区间0变1,1变0 每次输出从头开始扫描就行(我忘了珂朵莉树的性质,竟然还动态维护最左 ...
- 题解 CF375D 【Tree and Queries】
首先,子树上的查询问题可以通过$DFS$序转为序列问题 再一看,没有修改,可以离线,这不就是莫队吗? 我们用$sum_i$表示出现次数$\geq i$的个数 用$val_i$表示第$i$种颜色的出现次 ...
- 题解 UVA1479 【Graph and Queries】
\[ \text{Preface} \] 算是一道思维难度稍易,代码难度稍难的题吧. \[ \text{Description} \] 给出一张 \(n\) 个点,\(m\) 条边的图,点带权.需要支 ...
- 题解 CF938G 【Shortest Path Queries】
题目让我们维护一个连通无向图,边有边权,支持加边删边和询问从\(x\)到\(y\)的异或最短路. 考虑到有删边这样的撤销操作,那么用线段树分治来实现,用线段树来维护询问的时间轴. 将每一条边的出现时间 ...
- 【题解】CF375D Tree and Queries
Link \(\text{Solution:}\) 讲实话这题有点烦,不知道为啥改了下\(\text{dfs}\)就过了--原版本\(dfs\)好像没啥错啊-- 其实对于子树问题,我们求出原来树的\( ...
- 题解 Yet Another Number Sequence
题目传送门 Description 给出 \(n,k\) ,求出: \[\sum_{i=1}^{n} f_i·i^k \] 其中 \(f_i\) 表示斐波拉契第 \(i\) 项.\(n\le 10^{ ...
- Ural 1248 Sequence Sum 题解
目录 Ural 1248 Sequence Sum 题解 题意 题解 程序 Ural 1248 Sequence Sum 题解 题意 给定\(n\)个用科学计数法表示的实数\((10^{-100}\s ...
- 2015 Multi-University Training Contest 1 题解&&总结
---------- HDU 5288 OO’s Sequence 题意 给定一个数列(长度<$10^5$),求有多少区间[l,r],且区间内有多少数,满足区间内其它数不是他的约数. 数的范围$ ...
随机推荐
- 史上最全shell脚本编程语法上册
1. shell 脚本语言的基本用法 1.1 shell 脚本的用途 将简单的命令组合完成复杂的工作,自动化执行命令,提高工作效率: 减少手工命令的输入,一定程度上避免人为错误: 将软件或应用的安装及 ...
- Flutter(九)Json序列化与反序列化(转Model)
在日常开发中JSON的序列化与反序列化是一个常见的操作:而Dart语言不支持反射,运行时反射会影响Dart的tree shaking(摇树优化),tree shaking可以"抖掉" ...
- 『手撕Vue-CLI』函数柯里化优化代码
开篇 在上一篇文章中,给 nue-cli 添加了拉取版本号的功能,这一次来优化一下代码,使用函数柯里化的方式来优化代码. 实现 函数柯里化 函数柯里化是一种将使用多个参数的一个函数转换成一系列使用一个 ...
- OpenTelemetry agent 对 Spring Boot 应用的影响:一次 SPI 失效的案例
背景 前段时间公司领导让我排查一个关于在 JDK21 环境中使用 Spring Boot 配合一个 JDK18 新增的一个 SPI(java.net.spi.InetAddressResolverPr ...
- wordpress 折腾记
今天我看到一篇个人博客,我想建个人网站的心又动了. 虽说博客园已经很符合我的预期了,但我还是一直很想做一个个人网站做一些个性化的东西,今天试试用用wordpress搭建一个wordpress网站 介绍 ...
- Python中多线程的简单使用
from threading import Timer import time def run1(): print(1) print(2) print(3) def run2(): print(&qu ...
- Visual Studio(VS)常用快捷键整理
前言 在使用Visual Studio编写代码时,使用快捷键能够提高编码效率,作为程序员,我们有必要记住一些比较常用的快捷键.这篇文章将记录我自己比较常用的快捷键,并根据我的使用情况,更新常用快捷 ...
- koishi-跨平台、可扩展、高性能的机器人
koishi 介绍 Koishi 是一个跨平台.可扩展.高性能的聊天机器人框架. 它的名字和图标设计来源于东方 Project 中的角色 古明地恋 (Komeiji Koishi).古明地恋是一个会做 ...
- 修改带有强签名的DLL并重新生成
一.如果含有强签名,需要先使用去除强签名工具,这里使用的是"StrongNameRemove",点击修正就可以了,如果没有强签名可直接下一步: 二.将没有强签名的DLL进行反编译, ...
- 关于excel表
对excel表的操作主要通过xlwt,xlrd模块. 创建excel表 import xlwtworkbook = xlwt.Workbook(encoding='utf-8') worksheet ...