首页 > 其他分享 >题解:AT_abc357_f [ABC357F] Two Sequence Queries

题解:AT_abc357_f [ABC357F] Two Sequence Queries

时间:2024-07-17 16:58:59浏览次数:7  
标签:ch Sequence int 题解 Two ab ta tb mod

题意

维护一个数据结构,支持两个数列的区间求和,和查询区间内两数列各元素积的和。

分析

线段树万岁!

这道题要维护两个序列,所以线段树中要同时存储两个区间和。但还要在维护一个信息,是该区间内两序列元素积的和。大概长这样:

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;
}

标签:ch,Sequence,int,题解,Two,ab,ta,tb,mod
From: https://www.cnblogs.com/fengyixuan2027/p/18307813

相关文章

  • ABC357-C题解
    最近一直掉分,谔谔。分析发现机房里面除了我以外都用递归写的,那我就来讲一种非递归的吧。考虑第\(i\)级地毯拆成九块以后其实就是八块第\(i-1\)级地毯与一块大小为\(3^{i-1}\times3^{i-1}\)大小的白色地毯。所以用一个三维数组记录每一级地毯的状态,然后循环往上跑,每一级......
  • 题解:P10417 [蓝桥杯 2023 国 A] 第 K 小的和
    分析这道题不是板子么。先对序列排序,然后二分答案,设当前答案为\(x\),枚举\(a\)中的数,然后二分查找\(b\)中不大于\(x-a\)的元素个数,累加判断是否不大于\(k\)。然后稍微调一调端点就过了。Code#include<bits/stdc++.h>#include<ext/pb_ds/assoc_container.hpp>#incl......
  • 题解:AT_abc359_e [ABC359E] Water Tank
    背景中考结束了,但是暑假只有一天,这就是我现在能在机房里面写题解的原因……分析这道题就是个单调栈。题目上问你第一滴水流到每个位置的时间。我们考虑,答案其实就是比当前木板高且距离当前木板最近的那一个位置的答案加上当前木板的高度与那一个位置的距离构成的矩形面积再减......
  • 题解:P10672 【MX-S1-T1】壁垒
    暑期集训=依托答辩。分析种类数是奇数一定无解。否则每种数字先输出一次,在此过程中每增加两个数时,因为每个数字种类数都不一样,所以前缀种类数也同时增加\(2\),保证一定为偶数。然后输出完以后,设总种类数为\(m\),无论以后再怎么加入新数字,前缀种类数一定为\(m\)不变,后面数字......
  • 题解:AT_arc173_b [ARC173B] Make Many Triangles
    背景前几天打了比赛,崩麻了,所以来水一篇题解。LC真睿智题意给你\(n\)个点,问最多能组成几个三角形。分析听说可以随机化。这道题就是一个简单贪心。我们考虑,如果没有共线的点,那么答案显然就是\(\frac{n}{3}\)了。如果有共线,我们容易想到一个贪心思路:既然同一直线上的点不......
  • Divide Interval 题解
    背景太逊了,调了三次才调出来,所以写篇题解寄念。LC好睿智题意给你两个数\(a,b\),现在要从\(a\)跑到\(b\),每次可以将当前的\(a\)拆分成\(2^n\timesm(n,m\inN)\)的形式,并将它变成\(2^n\times(m+1)\)。问最少变几次能跑到\(b\),输出次数和每次变化前后\(a\)的值。分......
  • 题解:AT_abc352_d [ABC352D] Permutation Subsequence
    虽然比赛没打,但是想来水估值发表思路。题意给你一个\(1\simn\)的排列,让你从中找一段长为\(k\)的子序列,使得这个子序列中的元素排序后数值连续。分析题意转换一下,先用结构体存储每个元素的编号和数值,按照数值排序。于是这道题就成了:一个序列,让你求所有长\(k\)的子段中......
  • 有较复杂限制条件的dp(CF366C,POJ1837,CF294B题解+总结)
    前言这篇文章将用三道精选的好题例题让你学会这种类型的题目。题型看起来是一个背包,但是多了一个条件,是一个等式或不等式,有时候式子还挺复杂的,该怎么办呢?例题1CF366CDimaandSalad题意原题有n......
  • 洛谷P1596 [USACO10OCT] Lake Counting S 题解
    看别的神犇用的都是并查集,我还是用暴搜吧(doge下面纯暴搜#include<bits/stdc++.h>usingnamespacestd;intn,m,ans;//N行M列和答案charc[105][105];//存储农田的二维向量voiddfs(intx,inty){//暴搜 if(c[x][y+1]=='W'){ c[x][y+1]='.';//将水坑改为......
  • CodeForces Round 898 (div 4) H题解析
     CodeForcesRound898(div4)H.Mad City                           大致思路   对于有n条边和n个点,说明这个图里面只有一个环并且两人同时开始和结束移动,所以可以得到当Valeriu进入到这个图里面的唯一......