P1438 无聊的数列(差分&线段树)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1438 无聊的数列(差分&线段树)相关的知识,希望对你有一定的参考价值。
P1438 无聊的数列(差分&线段树)
区间加上等差数列,可以利用等差数列的差分数组相同的性质来做。
对于 [ L , R ] [L,R] [L,R]加上一个等差数列。
如:
原始区间: [ 0 , 0 , 0 , 0 , 0 , 0 ] [0,0,0,0,0,0] [0,0,0,0,0,0]
区间 [ 1 , 5 ] [1,5] [1,5]加上 [ 1 , 3 , 5 , 7 , 9 , 0 ] [1,3,5,7,9,0] [1,3,5,7,9,0]
[ 1 , 3 , 5 , 7 , 9 , 0 ] [1,3,5,7,9,0] [1,3,5,7,9,0]
差分数组变为: [ 1 , 2 , 2 , 2 , 2 , − 9 ] [1,2,2,2,2,-9] [1,2,2,2,2,−9]
即: a [ L ] + = k a[L]+=k a[L]+=k, [ L + 1 , R ] [L+1,R] [L+1,R]都加上 d d d。
a [ R + 1 ] − = ( k + ( R − L ) × d ) a[R+1]-=(k+(R-L)\\times d) a[R+1]−=(k+(R−L)×d)
然后就是裸的区间修改,区间求和。
code
// Problem: P1438 无聊的数列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1438
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-06 17:00:40
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
}
//if have char input #define should cancel
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline T& read(T& r) {
r = 0; bool w = 0; char ch = getchar();
while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
return r = w ? -r : r;
}
int n,m;
struct node{
int l,r;
int lz,s;
}a[N<<2];
#define lx x<<1
#define rx x<<1|1
int b[N];
void re(int x){
a[x].s=a[lx].s+a[rx].s;
}
void bud(int x,int l,int r){
a[x].l=l,a[x].r=r,a[x].s=0;
if(l==r){
a[x].s=b[l];return;
}
int mid=l+r>>1;
bud(lx,l,mid),bud(rx,mid+1,r);
re(x);
}
void pushdown(int x){
if(a[x].lz){
a[lx].lz+=a[x].lz,a[rx].lz+=a[x].lz;
a[lx].s+=(a[lx].r-a[lx].l+1)*a[x].lz;
a[rx].s+=(a[rx].r-a[rx].l+1)*a[x].lz;
a[x].lz=0;
}
}
void upd(int x,int l,int r,int v){
if(a[x].l>=l&&a[x].r<=r){
a[x].lz+=v;
a[x].s+=(a[x].r-a[x].l+1)*v;return;
}
pushdown(x);
int mid=a[x].l+a[x].r>>1;
if(l<=mid) upd(lx,l,r,v);
if(r>mid) upd(rx,l,r,v);
re(x);
}
int que(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r) return a[x].s;
pushdown(x);
int s=0;
int mid=a[x].l+a[x].r>>1;
if(l<=mid) s+=que(lx,l,r);
if(r>mid) s+=que(rx,l,r);
return s;
}
int main(){
read(n),read(m);
for(int i=1;i<=n;i++) read(b[i]);
for(int i=n;i;i--) b[i]=b[i]-b[i-1];
bud(1,1,n);
while(m--){
int op,l,r,d,k;
read(op);
if(op==1){
read(l),read(r),read(k),read(d);
upd(1,l,l,k);
if(l+1<=r) upd(1,l+1,r,d);
if(r<n) upd(1,r+1,r+1,-(k+(r-l)*d));
}
else {
int x;read(x);
printf("%d\\n",que(1,1,x));
}
}
return 0;
}
以上是关于P1438 无聊的数列(差分&线段树)的主要内容,如果未能解决你的问题,请参考以下文章