洛谷题目链接:无聊的数列
题目背景
无聊的YYB总喜欢搞出一些正常人无法搞出的东西。有一天,无聊的YYB想出了一道无聊的题:无聊的数列。。。(K峰:这题不是傻X题吗)
题目描述
维护一个数列{a[i]},支持两种操作:
1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,
a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。
2、2 P:询问序列的第P个数的值a[P]。
输入输出格式
输入格式:
第一行两个整数数n,m,表示数列长度和操作个数。
第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。
接下来的m行,表示m个操作,有两种形式:
1 L R K D
2 P 字母意义见描述(L≤R)。
输出格式:
对于每个询问,输出答案,每个答案占一行。
输入输出样例
输入样例#1: 复制
5 2
1 2 3 4 5
1 2 4 1 2
2 3
输出样例#1: 复制
6
说明
数据规模:
0≤n,m≤100000
|a[i]|,|K|,|D|≤200
分析一下题意:给出一个长度为n的序列,m次操作,单点修改和区间修改,单点查询.
做法:
- 差分记录修改
- 线段树维护区间
- 查询时输出修改的值加原值
下面贴一下代码:
#include<bits/stdc++.h>
#define ll(x) (x<<1)
#define rr(x) (x<<1|1)
using namespace std;
const int N=100000+5;
int n, m, w[N];
struct segment_tree{
int l, r, sum, tag;
}t[N*4];
int gi(){
int ans = 0 , f = 1; char i = getchar();
while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
return ans * f;
}
void up(int x){
t[x].sum = t[ll(x)].sum+t[rr(x)].sum;
}
void build(int node,int l,int r){
t[node].l = l; t[node].r = r;
if(l == r) return;
int mid = (l+r>>1);
build(ll(node),l,mid);
build(rr(node),mid+1,r);
up(node);
}
void pushdown(int node){
int ls = ll(node), rs = rr(node), tag = t[node].tag;
int l = t[node].l, r = t[node].r , mid = (l+r>>1);
t[ls].tag += tag; t[rs].tag += tag;
t[ls].sum += tag*(mid-l+1); t[rs].sum += tag*(r-mid);
t[node].tag = 0;
}
void updata(int node,int l,int r,int val){
if(l <= t[node].l && t[node].r <= r){
t[node].tag += val;
t[node].sum += val*(t[node].r-t[node].l+1);
return;
}
if(t[node].tag) pushdown(node);
int mid = (t[node].l+t[node].r>>1);
if(l <= mid) updata(ll(node),l,r,val);
if(mid < r) updata(rr(node),l,r,val);
up(node);
}
int query(int node,int l,int r){
if(l <= t[node].l && t[node].r <= r) return t[node].sum;
if(r < t[node].l || t[node].r < l) return 0;
if(t[node].tag) pushdown(node);
return query(ll(node),l,r)+query(rr(node),l,r);
}
int main(){
//freopen("data.in","r",stdin);
int flag, l, r, k, d; n = gi(); m = gi();
for(int i=1;i<=n;i++) w[i] = gi();
build(1,1,n);
while(m--){
flag = gi(); l = gi();
if(flag == 1){
r = gi(); k = gi(); d = gi();
updata(1,l+1,r,d); updata(1,l,l,k);
if(r+1 <= n) updata(1,r+1,r+1,-d*(r-l)-k);//因为建树的时候没有建n+1的下标,所以特判防越界
}
else printf("%d
",w[l]+query(1,1,l));
}
return 0;
}