题目描述
给出一个长为的数列,以及个操作,操作涉及区间加法,单点查值。
输入格式
第一行输入一个数字 。
第二行输入个数字,第i个数字为,以空格隔开。
接下来输入行询问,每行输入四个数字、、、,以空格隔开。
若 =1,表示将位于 的之间的数字都加 。
若 =0,表示询问 的值(和忽略)。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
Input | Output |
---|---|
| |
代码
#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N = 50007;
int l[N],r[N],block,num,belong[N],n,x,y;
ll a[N],lazy[N];
inline void build()
{
block=sqrt(n);
//block代表的是完整分块的长度
num=n/block;if (n%num) num++;
//num表示分块的块的个数
for (int i=1;i<=num;i++)
l[i]=(i-1)*block+1,r[i]=i*block;
//l[i],r[i]代表的是第i个块的左/右的a数组下标
r[num]=n;
//不完整块
for (int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
//belong代表的是当前a[i]这个数是属于哪个块
}
inline void update(int x,int y,int c)
{
if (belong[x]==belong[y])
{
for (int i=x;i<=y;i++) a[i]+=c;
return;
}
//不特判这个if下面的第一个循环和第三个循环可能会重复
for (int i=x;i<=r[belong[x]];i++) a[i]+=c;
//暴力美学
for (int i=belong[x]+1;i<belong[y];i++) lazy[i]+=c;
//同线段树 lazy标记
for (int i=l[belong[y]];i<=y;i++) a[i]+=c;
}
inline ll ask(int x)
{
return a[x]+lazy[belong[x]];
//还要加上lazy
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
IOS
cin>>n;
for (int i=1;i<=n;i++)
cin>>a[i];
build();
for (int k=1;k<=n;k++)
{
int l,r,op,c;
cin>>op>>l>>r>>c;
if (op==0)
update(l,r,c);
else
cout<<ask(r)<<endl;
}
return 0;
}