首页 > 其他分享 >AtCoder Beginner Contest 357-F

AtCoder Beginner Contest 357-F

时间:2024-06-21 10:45:46浏览次数:17  
标签:AtCoder Beginner sum sumB 357 leq LL sumA define

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,sum,sumB,357,leq,LL,sumA,define
From: https://www.cnblogs.com/Vanilla-chan/p/18260061

相关文章

  • AtCoder Beginner Contest 358
    A-WelcometoAtCoderLandvoidsolve(){strings,t;cin>>s>>t;if(s=="AtCoder"&&t=="Land"){cout<<"Yes\n";return;}cout<<"No\n&qu......
  • [atcoder 358] 【动态规划】
    dp[i][j]表示前i个和为j的个数。那么就有递推式dp[i][j]+=dp[i][j-x]*c(j,j-x);其中x满足从0到c[i],并且x满足<=j组合数递推公式c(n,k)=c(n,k-1)+c(n,k);importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;impor......
  • ATcoder ABC 358 补题记录(A~D,G)
    A直接模拟即可。#pragmaGCCoptimize(3)#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1000100,mod=998244353;inta[N];signedmain(){strings,t;cin>>s>>t;if(s=="AtCoder"&&t==&qu......
  • ABC357
    Alink循环加每一个数,加到哪个数不能加了输出前一个数,注意如果加到最后还能加,记得输出\(n\)。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,m;inth[105],sum;signedmain(){ cin>>n>>m; for(inti=1;i<=n;++i) cin>>h[i]; for......
  • atcoder 官方dp题单题解(持续更新)
    题单链接:https://atcoder.jp/contests/dp/tasks洛谷搜索:https://www.luogu.com.cn/problem/list?keyword=at_dp&type=AT|B|CF|P|SP|UVA&page=1A题目链接:https://atcoder.jp/contests/dp/tasks/dp_a简单线性dp.dp[i]表示在i这个位置的最小代价,转移的时候把两种选择都考虑......
  • 由AtCoder_ABC357D引发的除法同余学习
    鉴于最近的Atcoder周赛又出现除法求余,下定决心学习逆元相关内容同余概述定义同余定义:若a和b是整数,且m|(a-b),则称a和b模m同余。即两者除以m得到的余数相同。剩余系:一个模m完全剩余系是一个整数集合,任何一个整数恰好与该集合中的一个元素模m同余。例如0,1,...,m-1的集......
  • Atcoder357D题解(求解等比数列求和公式的推导)
    解题思路设连接之后的N等于Nlast,w=10^(N在10进制下的长度,例如N=5,那么w=10)Nlast=N+N*w+N*(w^2)+N*(w^3)+.....+N*(w^n)举个例子N=5,因为510进制的长度是1,所以w=10,那么Nlast=5+5*10(w)^1+5*10(w)^2+5*10(w)^3+......
  • Atcoder357 D(逆元和快速幂)
    Atcoder357DD题意就是求给定一个数n的连续n个n相拼接,求最后的数\(mod998244353\)的值。我们假设n的长度为len,那么n个n相拼接可以看成n*(\(10^{len^0}\)+\(10^{len^1}\)+....+\(10^{len^{n-1}}\))。那个就可以利用高中等比数列的知识求出公式(\(n*(10^{len^n}-1\))/(\(10^{len}......
  • AtCoder Beginner Contest 357
    ABC357总结AtCoderBeginnerContest357A-SanitizeHands翻译有一瓶消毒剂,正好可以消毒\(M\)双手。\(N\)名外星人陆续前来消毒双手。\(i\)个外星人(\(1\leqi\leqN\))有\(H_i\)只手,想把所有的手都消毒一次。请计算有多少个外星人可以给所有的手消毒。在这里,即......
  • SuntoryProgrammingContest2024(AtCoder Beginner Contest 357)
    A-SanitizeHands题意:给定一个序列和m,问m按顺序减去这个序列,m>=0情况下最多能减多少个数思路:前缀和+prev(upper_bound())总结:disinfectan(消毒ji),disinfect(消毒,杀毒),aliens(外星人),voidsolve(){ intn,m; cin>>n>>m; vector<int>a(n); for(inti=......