P1438 无聊的数列
作者:互联网
分析
老规矩,先看操作
1 l r K D
:给出一个长度等于 r-l+1 的等差数列,首项为 K,公差为 D,并将它对应加到 [l,r] 范围中的每一个数上。即令 \(a_l=a_l+K,a_{l+1}=a_{l+1}+K+D\ldots a_r=a_r+K+(r-l) \times D\)2 p
:询问序列的第 p 个数的值 \(a_p\)。
一看第一个操作,给一个区间的每个数递增的增加数,这妥妥要用差分数组完成啊。
区间修改,单点查询。
我们直接维护差分数组。
操作一:
对l加K,对[l-1,r]加D,对r+1减K+(r-l)*D,结束了,记得边界问题。
操作二:
直接查询[1,r]的区间和,即为\(a_p\)了。
Ac_code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
struct Node
{
int l,r;
LL sum,tag;
}tr[N<<2];
int a[N],b[N];
int n,m;
void pushup(int u)
{
tr[u].sum = tr[u<<1].sum + tr[u<<1|1].sum;
}
void build(int u,int l,int r)
{
if(l==r)
{
tr[u] = {l,r,b[l],0};
return;
}
tr[u] = {l,r};
int mid = l + r >> 1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void pushdown(int u)
{
auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1];
if(root.tag)
{
left.sum += 1ll*(left.r - left.l + 1)*root.tag;
left.tag += root.tag;
right.sum += 1ll*(right.r - right.l + 1)*root.tag;
right.tag += root.tag;
root.tag = 0;
}
}
void modify(int u,int l,int r,int k)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
tr[u].sum += 1ll*(tr[u].r - tr[u].l + 1)*k;
tr[u].tag += k;
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l<=mid) modify(u<<1,l,r,k);
if(r>mid) modify(u<<1|1,l,r,k);
pushup(u);
}
LL query(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
LL res = 0;
if(l<=mid) res += query(u<<1,l,r);
if(r>mid) res += query(u<<1|1,l,r);
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",a+i);
for(int i=1;i<=n;i++) b[i] = a[i] - a[i-1];
build(1,1,n);
while(m--)
{
int op;scanf("%d",&op);
if(op==1)
{
int l,r,k,d;scanf("%d%d%d%d",&l,&r,&k,&d);
modify(1,l,l,k);
if(r<n) modify(1,r+1,r+1,-k-(r-l)*d);
if(l<n) modify(1,l+1,r,d);
}
else
{
int p;
scanf("%d",&p);
printf("%lld\n",query(1,1,p));
}
}
return 0;
}
标签:数列,无聊,res,LL,long,int,lmid,P1438 来源: https://www.cnblogs.com/aitejiu/p/16244265.html