Problem

同步于博客

Problem

You are given sequences of length \(N\), \(A=(A_1,A_2,\ldots,A_N)\) and \(B=(B_1,B_2,\ldots,B_N)\).

You are also given \(Q\) queries to process in order.

There are three types of queries:

  • 1 l r x : Add \(x\) to each of \(A_l, A_{l+1}, \ldots, A_r\).
  • 2 l r x : Add \(x\) to each of \(B_l, B_{l+1}, \ldots, B_r\).
  • 3 l r : Print the remainder of \(\displaystyle\sum_{i=l}^r (A_i\times B_i)\) when divided by \(998244353\).

给你两个长度为 \(N\) 的序列 \(A=(A_1,A_2,\ldots,A_N)\) 和 \(B=(B_1,B_2,\ldots,B_N)\) 的序列。

需要按顺序处理 \(Q\) 个查询。

查询有三种类型:

  • 1 l r x : 在 \(A_l, A_{l+1}, \ldots, A_r\) 中的每一条添加 \(x\) 。
  • 2 l r x : 向 \(B_l, B_{l+1}, \ldots, B_r\) 中的每一条添加 \(x\) 。
  • 3 l r : 打印 \(\displaystyle\sum_{i=l}^r (A_i\times B_i)\) 除以 \(998244353\) 的余数。

Constraints

  • \(1\leq N,Q\leq 2\times 10^5\)
  • \(0\leq A_i,B_i\leq 10^9\)
  • \(1\leq l\leq r\leq N\)
  • \(1\leq x\leq 10^9\)
  • 全是整数

Solution

看到 \(N,Q\) 的取值范围,发现需要在 \(n\log n\) 的复杂度内解决。值域 \(1\le x\le 10^9\) 也不好做文章。

数列\(A,B\)在\([l,r]\)上在进行操作1 l r x2 l r y后会变为

\[\begin{align}
&\sum_{i=l}^r(A_i+x)\times (B_i+y)\\
&=\sum_{i=l}^rA_i\times B_i+x\sum_{i=l}^r B_i+y\sum_{i=l}^r A_i+xy(r-l+1)
\end{align}
\]

故我们使用线段树维护三个量 \(\sum A_i\times B_i,\sum A_i,\sum B_i\) 和lazy标记 \(Add_a,Add_b\)

当执行1 l r x

  • \(\sum A_i\times B_i\) 增加 \(x\sum B_i+x\cdot Add_b\cdot(r-l+1)\)​
  • \(\sum A_i\) 增加 \(x(r-l+1)\)
  • \(Add_a\) 增加 \(x\)

当执行2 l r y

  • \(\sum A_i\times B_i\) 增加 \(y\sum A_i+y\cdot Add_a\cdot(r-l+1)\)​
  • \(\sum B_i\) 增加 \(y(r-l+1)\)
  • \(Add_b\) 增加 \(y\)

Code

#define P 998244353ll
#define N 800010
struct Edge{
LL l,r,sumA,sumB,sum,addA,addB;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sumA(x) tree[x].sumA
#define sumB(x) tree[x].sumB
#define sum(x) tree[x].sum
#define addA(x) tree[x].addA
#define addB(x) tree[x].addB
}tree[N];
LL n,m;
LL A[N],B[N];
void build(LL l,LL r,LL p)
{
l(p)=l,r(p)=r;
if(l==r){sumA(p)=A[l]%P;sumB(p)=B[l]%P;sum(p)=sumA(p)*sumB(p)%P;return;}
LL mid=(l+r)>>1;
build(l,mid,p<<1);
build(mid+1,r,p<<1|1);
sum(p)=sum(p<<1)+sum(p<<1|1);
sumA(p)=sumA(p<<1)+sumA(p<<1|1);
sumB(p)=sumB(p<<1)+sumB(p<<1|1);
sum(p)%=P;
sumA(p)%=P;
sumB(p)%=P;
}
void spread(LL p)
{
if(addA(p)||addB(p))
{
addA(p<<1)+=addA(p);
addA(p<<1|1)+=addA(p);
addB(p<<1)+=addB(p);
addB(p<<1|1)+=addB(p); sum(p<<1)+=addA(p)*sumB(p<<1)+addB(p)*sumA(p<<1)+addA(p)*addB(p)%P*(r(p<<1)-l(p<<1)+1);
sum(p<<1|1)+=addA(p)*sumB(p<<1|1)+addB(p)*sumA(p<<1|1)+addA(p)*addB(p)%P*(r(p<<1|1)-l(p<<1|1)+1); sumA(p<<1)+=addA(p)*(r(p<<1)-l(p<<1)+1);
sumB(p<<1)+=addB(p)*(r(p<<1)-l(p<<1)+1);
sumA(p<<1|1)+=addA(p)*(r(p<<1|1)-l(p<<1|1)+1);
sumB(p<<1|1)+=addB(p)*(r(p<<1|1)-l(p<<1|1)+1); addA(p)=addB(p)=0; sum(p<<1)%=P;
sum(p<<1|1)%=P;
sumA(p<<1)%=P;
sumA(p<<1|1)%=P;
sumB(p<<1)%=P;
sumB(p<<1|1)%=P; addA(p<<1)%=P;
addB(p<<1)%=P;
addA(p<<1|1)%=P;
addB(p<<1|1)%=P;
}
}
void change(LL l,LL r,LL p,LL k,bool isA)
{
if(l<=l(p)&&r>=r(p)){
if(isA) addA(p)+=k,sum(p)+=k*sumB(p),sumA(p)+=k*(r(p)-l(p)+1);
else addB(p)+=k,sum(p)+=k*sumA(p),sumB(p)+=k*(r(p)-l(p)+1);
sumA(p)%=P;sumB(p)%=P;sum(p)%=P;
addA(p)%=P;addB(p)%=P;
return;
}
LL mid=l(p)+r(p)>>1;
spread(p);
if(l<=mid) change(l,r,p<<1,k,isA);
if(r>mid) change(l,r,p<<1|1,k,isA);
sum(p)=sum(p<<1)+sum(p<<1|1);
sumA(p)=sumA(p<<1)+sumA(p<<1|1);
sumB(p)=sumB(p<<1)+sumB(p<<1|1);
sum(p)%=P;
sumA(p)%=P;
sumB(p)%=P;
} LL ask(LL l,LL r,LL p)
{
if(l<=l(p)&&r>=r(p)) return sum(p);
spread(p);
LL mid=l(p)+r(p)>>1,val=0;
if(l<=mid) val+=ask(l,r,p<<1);
val%=P;
if(r>mid) val+=ask(l,r,p<<1|1);
val%=P;
return val;
} int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(10);
int q;
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>A[i];
for(int i=1;i<=n;i++) cin>>B[i];
build(1,n,1);
while(q--)
{
int op,l,r,x;
cin>>op>>l>>r;
if(op!=3) cin>>x,change(l,r,1,x,(op==1));
else cout<<ask(l,r,1)<<endl;
}
return 0;
}

Attention

开LL,多取模。

AtCoder Beginner Contest 357-F的更多相关文章

  1. AtCoder Beginner Contest 137 F

    AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...

  2. AtCoder Beginner Contest 261 F // 树状数组

    题目链接:F - Sorting Color Balls (atcoder.jp) 题意: 有n个球,球有颜色和数字.对相邻的两球进行交换时,若颜色不同,需要花费1的代价.求将球排成数字不降的顺序,所 ...

  3. AtCoder Beginner Contest 260 F - Find 4-cycle

    题目传送门:F - Find 4-cycle (atcoder.jp) 题意: 给定一个无向图,其包含了S.T两个独立点集(即S.T内部间的任意两点之间不存在边),再给出图中的M条边(S中的点与T中的 ...

  4. AtCoder Beginner Contest 253 F - Operations on a Matrix // 树状数组

    题目传送门:F - Operations on a Matrix (atcoder.jp) 题意: 给一个N*M大小的零矩阵,以及Q次操作.操作1(l,r,x):对于 [l,r] 区间内的每列都加上x ...

  5. AtCoder Beginner Contest 249 F - Ignore Operations // 贪心 + 大根堆

    传送门:F - Keep Connect (atcoder.jp) 题意: 给定长度为N的操作(ti,yi). 给定初值为0的x,对其进行操作:当t为1时,将x替换为y:当t为2时,将x加上y. 最多 ...

  6. AtCoder Beginner Contest 247 F - Cards // dp + 并查集

    原题链接:F - Cards (atcoder.jp) 题意: 给定N张牌,每张牌正反面各有一个数,所有牌的正面.反面分别构成大小为N的排列P,Q. 求有多少种摆放方式,使得N张牌朝上的数字构成一个1 ...

  7. AtCoder Beginner Contest 133 F Colorful Tree

    Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...

  8. AtCoder Beginner Contest 171-175 F

    171 F - Strivore 直接把初始字符当成隔板,统计的方案数会有重复 为了避免重复情况,规定隔板字母尽可能最后出现,即在隔板字母后面不能插入含隔板字母的字符串 所以在隔板字母后插入的字符只有 ...

  9. AtCoder Beginner Contest 182 F

    F - Valid payments 简化题意:有\(n\)种面值的货币,保证\(a[1]=1,且a[i+1]是a[i]的倍数\). 有一个价格为\(x\)元的商品,付款\(y\)元,找零\(y-x\ ...

  10. AtCoder Beginner Contest 215 F题题解

    F - Dist Max 2 什么时候我才能突破\(F\)题的大关... 算了,不说了,看题. 简化题意:给定\(n\)个点的坐标,定义没两个点的距离为\(min(|x_i-x_j|,|y_i-y_j ...

随机推荐

  1. Linux下配置系统ipv6环境

    一:检查Linux是否已经开启ipv6 1.使用 ifconfig 查看自己的IP地址是否含有IPv6地址. inet6 addr: fe80::213:d4f*:****:****/64 Scope ...

  2. DevOps - DevOps基础概念梳理

    目录 DevOps DevOps的好处与价值 可能的几个关注点 DevOps能力环 DevOps与持续集成.持续交付 一个完整的过程 典型的CICD流水线过程 DevOps黄金思维圈 初见 一些图示 ...

  3. 配置win + ubuntu双系统需要注意的一些点

    配置win + ubuntu双系统需要注意的一些点 基本上是按照B站机器人工匠阿杰的视频来的,但是有一些需要注意的点值得关注. 关闭RST 首先是比较新的电脑bios里会有一个叫做英特尔 快速存储技术 ...

  4. c-primer-plus深入解读系列-从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜

    前言 小提示:阅读本篇内容,至少需要了解double和float的二进制表示规则. 书中的代码示例如下: #include <stdio.h> int main(void) { float ...

  5. 【Java】RESTful风格

    RESTful风格 REST:即 Representational State Transfer.(资源)表现层状态转化.是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所 ...

  6. Python 潮流周刊#96:MCP 到底是什么?(摘要)

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...

  7. 【ESP32】移植 Arduino 库到 idf 项目中

    今天咱们要聊的内容非常简单,所以先扯点别的.上一篇水文中,老周没能将 TinyUSB 的源码编译进 Arduino 中,心有两百万个不甘,于是清明节的时候再试了一次,居然成功了,已经在 esp32 开 ...

  8. go: no such tool "compile"(记录)

    这是一次离谱问题和胡搞一通莫名解决的记录 背景:win11系统下,原有的go1.18更新到go1.19后出现了莫名的go: no sucn tool "compile"的情况. 当 ...

  9. 🎯Vercel-从零到上线的云端部署神器

    简介 Vercel是一个专注于前端和全栈应用部署的云端平台,由Zeit公司开发.它以零配置部署.全球CDN加速和对主流框架的深度支持为核心优势,成为开发者快速上线项目的首选工具.无论是个人博客.企业官 ...

  10. 关于while循环与for循环

    首先看for循环 def test(): print('1') print('2') for i in range(3): test() 执行后的结果,按照下图所示,for循环就是把指定的函数重复执行 ...