首页 > 其他分享 >无聊的数列[题解]

无聊的数列[题解]

时间:2024-03-09 15:47:23浏览次数:26  
标签:数列 无聊 题解 ll 差分 st 加上 add

无聊的数列


[link1] [link2]


题目大意

给定一个数列 \(A\)
有两种操作:

  • 将数列中 \(A_i\) (\(L \leq i \leq R\)) 加上一个等差数列(首项D 公差K)
  • 查询数列中第P位数

区间加上一个等差数列可以用差分来解决

原序列:0 0 0 0 0 0
差分序列:0 0 0 0 0 0
等差序列:1 3 5 7 9(首项1 公差2 L=1 R=5)
加上等差数列后的序列:1 3 5 7 9 0
然后差分:1 2 2 2 2 -9

我们可以发现,后来的差分序列中:

对于[L],加上了首项1
对于[L+1,R],每项都加上了公差2
对于[R+1],减去了末项9

所以该题是一个差分数组上区间修改,单点查询的题 即线段树


我们可以用线段树来维护差分数组
对于每个加上等差数列
我们可以:

[L]加上了首项
[L+1,R]加上公差
[R+1]减去末项

注:

L和R可能大于n!!!

所以要特判!!!

坑啊


所以代码就是

#include<bits/stdc++.h>
#define put(n) scanf("%lld",&n) 
#define out(n) printf("%lld\n",n)
#define ll long long
using namespace std;
ll n,m,a[5001000];
struct ST
{
	ll l,r;
	ll add,ans;//懒标记 答案 
}st[20001000];
void upd(ll p)
{
	st[p].ans=(st[p<<1].ans+st[p<<1|1].ans); 
}
void spread(ll p) //参考 区间加 代码 
{
	st[p<<1].ans+=st[p].add*(st[p<<1].r-st[p<<1].l+1); 
	st[p<<1|1].ans+=st[p].add*(st[p<<1|1].r-st[p<<1|1].l+1);
	//两儿子 总和加上其长度*add 
	st[p<<1].add+=st[p].add;
	st[p<<1|1].add+=st[p].add;
	//下传 
	st[p].add=0;
	//清空 
}
void build(ll p,ll l,ll r)
{
	st[p].l=l;
	st[p].r=r;
	st[p].add=st[p].ans=0;
	if(l==r)
	{
		st[p].ans=a[l]-a[l-1];//差分 
		return;
	}
	ll mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	upd(p);
}
ll ask(ll p,ll l,ll r)//求区间和代码 
{
	if(l<=st[p].l&&r>=st[p].r)
		return st[p].ans;
	spread(p);
	ll mid=(st[p].l+st[p].r)>>1;
	ll sum=0;
	if(l<=mid) sum+=ask(p<<1,l,r);
	if(r>mid) sum+=ask(p<<1|1,l,r);
	return sum;
}
void change(ll p,ll l,ll r,ll q)
{
	if(l<=st[p].l&&r>=st[p].r)
	{
		st[p].ans+=q*(st[p].r-st[p].l+1);//总和加上其长度*add 
		st[p].add=st[p].add+q;//更新add 
		return;
	}
	spread(p);
	ll mid=(st[p].l+st[p].r)>>1;
	if(l<=mid) change(p<<1,l,r,q);
	if(r>mid) change(p<<1|1,l,r,q);
	upd(p);
}
int main()
{
	freopen("boring.in","r",stdin);
	freopen("boring.out","w",stdout);
	scanf("%lld",&n);
	scanf("%lld",&m);
	for(ll i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
	}
	build(1,1,n);
	for(ll i=1;i<=m;i++)
	{
		ll opt,dd,le,ri,kk;
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld%lld",&le,&ri,&kk,&dd);
			if(le<n)//坑 
			{
				change(1ll,le,le,kk);//把L加上首项 
				if(ri<=n) change(1ll,le+1,ri,dd);//L+1 —R全加上公差 
				else change(1ll,le+1,n,dd);//坑 
			}
			if(ri<n) change(1ll,ri+1,ri+1,-(dd*(ri-le)+kk));//R+1减去末项
		}
		else
		{
			scanf("%lld",&kk);
			printf("%lld\n",ask(1ll,1,kk));
			/*
			查询差分数组前缀和
			而不是ask(1,kk,kk)+a[kk] 
			*/
		}
	}
	return 0;
}

标签:数列,无聊,题解,ll,差分,st,加上,add
From: https://www.cnblogs.com/whrwlx/p/18062779

相关文章

  • 课堂练习 最大值 原题链接+题解
    题目可以去我的洛谷题库看:https://www.luogu.com.cn/problem/U412348(带数据,真难出)题解考虑两种解题方式。由于题目范围较小,可以check+暴力,如果范围大一点,可以check+二分答案。先讲check函数,小学四年级数学书说了,这种问题也被它叫做“铺地砖”问题,计算剪出的正方形数量的方......
  • 一本通 1270 混合背包 题解
    是在hydro上做的,墙裂推荐hydro的一本通题库!链接是:https://hydro.ac/d/ybttk/p/T1270。分析一下,可以分类讨论,处理的时候,零一背包(\(p_i=1\))一个,完全背包(\(p_i=0\))一个,多重背包(\(p_i>1\))一个,状态转移方程不用列的,直接去抄模板就可以啦~代码是这样的捏:#include<bits/st......
  • P6583 回首过去 题解
    P6583回首过去题解题目传送门好题。更新(2023-12-05):把代码和$\LaTeX$改得更好看了。题意简述给定正整数$n$,求出有序整数对$(x,y)$的个数,满足$1\lex,y\len$且$\dfracxy$可以表示为十进制有限小数。$1\len\le10^{12}$。前置知识数论分块解法Subtas......
  • CF1846D Rudolph and Christmas Tree 题解
    因为\(n\)个三角形有重叠部分,所以我们可以倒序处理每个三角形,并对其进行分类讨论:若当前三角形编号为\(n\),则直接将总面积加上\(\dfrac{d\timesh}{2}\)。否则,再次分出两种情况:若当前三角形的\(y_i+h>y_{i+1}\)(即编号为\(i,i+1\)的三角形有重叠),则如下图所示:......
  • CF387B George and Round 题解
    考虑采用双指针法解决此题。首先需要对\(a,b\)数组排序,并且维护两个指针\(l,r\),分别指向\(a,b\)两个数组中的元素。接着循环移动\(r\)指针,每次都尝试匹配\(a_l\)和\(b_r\):若\(a_l\leb_r\),则说明\(a_l=b_r\)或可以采用减少\(b_r\)的方式使\(a_l=b_r\),这......
  • P3670 [USACO17OPEN] Bovine Genomics S 题解
    题意给定\(2\)组字符串,每组\(n\)个,每个字符串包含\(m\)个字符。我们称一个三元组\((i,j,k)\)是合法的,当且仅当第二组的每个字符串中下标为\((i,j,k)\)的字符拼成的字符串与第一组的每个字符串中下标为\((i,j,k)\)的字符拼成的字符串均不相等。现在需要你对于给定的......
  • CF99B Help Chef Gerasim 题解
    分别对三种情况进行分类讨论。第一种情况:显然,若\(\sum^{n}_{i=1}a_i\bmodn\neq0\),则输出\(\texttt{Unrecoverableconfiguration.}\);同时,我们遍历\(a_{1\simn}\),若存在两个以上的\(a_i\)满足\(a_i\neq\sum^{n}_{i=1}a_i\divn\),则也输出\(\texttt{Unreco......
  • P10217 [省选联考 2024] 季风题解
    考场上没写出来,火大,实际上这题放校内%你赛我肯定写的出来,可惜这是省选。实际上这题不难,主要是观察性质,接着拆柿子,然后就是有点难写,要写得好看有点考验代码构建能力和数学能力。我们考虑原题的每对\((x,y)\)都要满足\(|x|+|y|\lek\)而我们可以知道后面应该填的\((x,y)\)如......
  • CF348A Mafia 题解
    由于题目具有十分明显的单调性(若\(x\)局能满足要求,则\(>x\)局一定能满足;若\(x\)局无法满足要求,则\(<x\)局也无法满足),因此我们考虑进行二分答案。二分所需要的局数\(x\),设所有人想玩的总局数为\(S\),由题意可得\(S=\sum^{n}_{i=1}a_i\)。因为每局都会有\(1\)人主持,\(n......
  • [ABC297F] Minimum Bounding Box 2 题解
    容斥真有趣。有一个性质:两个相同的子矩阵,对答案的贡献一定相同。所以就只需要枚举矩阵大小即可。我们设当前矩阵长\(i\)宽\(j\)(对应的,\(H\)为长,\(W\)为宽),假如要给答案做出贡献,矩阵的四条边一定都有点,发现可以容斥了。至少\(0\)条边上有点的方案数为\(a=C_{i\times......