题意:
给出一个长为 nn 的数列,以及 个操作,操作涉及区间加法,单点查值。
题解:
1.将mm个元素分为一块,那么数列中至多也就只有块, 每次操作也就是至多涉及到n/mn/m个整块以及其附近的不完整的块中至多的2∗m2∗m个元素
2.给每个块设置一个加法tag, 这样的话我们每次标记的复杂度就是O(1)O(1), 附近的块的话 直接暴力修改即可, 每次询问时,返回元素在加上所在块的tag
3.复杂度分析: O(nn/m+nm),m=sqrt(n)O(nn/m+nm),m=sqrt(n)
树状数组: 直接维护一个差分数组
//
// Created by team02 on 18-8-17.
//
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ls o<<1
#define rs o<<1|1
#define fi first
#define se second
#define CLR(a, b) memset(a, (b), sizeof(a))
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int MAXN = 2e5+10;
void F() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
}
int a[MAXN],b[MAXN],add[MAXN];
int main() {
//F();
ios::sync_with_stdio(false);
int n;
cin >> n;
for(int i=1;i<=n;++i) cin>>a[i];
int k=(int)sqrt(n);
for(int i=1;i<=n;++i) b[i]=(i-1)/k+1; // 对每个大小为k的块打上标记
// for(int i=1;i<=n;++i) cout<<b[i]<<" ";
cout<<"\n";
int op,l,r,c;
while(n--){
cin>>op>>l>>r>>c;
if(op==0){
// 暴力修改左边的块内内容, 注意一个小trick: 修改的区间在一个块内
for(int i=l;i<=min(b[l]*k,r);++i) a[i]+=c;
// 如果左右区间不在一个块内, 则修改右边的块内区间
if(b[l]!=b[r])
for(int i=(b[r]-1)*k+1;i<=r;++i) a[i]+=c;
// 给区间内的每个块打上标记
for(int i=b[l]+1;i<=b[r]-1;++i) add[i]+=c;
}
else {
cout<<a[r]+add[b[r]]<<endl;
}
}
return 0;
}
//
// Created by team02 on 18-8-17.
//
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ls o<<1
#define rs o<<1|1
#define fi first
#define se second
#define CLR(a, b) memset(a, (b), sizeof(a))
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int MAXN = 2e5+10;
int n, c[MAXN],a[MAXN];
int lowbit(int x) { return x&(-x); }
void add(int p, int x) { while(p <= n) c[p]+=x, p+=lowbit(p); }
int query(int p) { int res = 0; while(p) res+=c[p],p-=lowbit(p); return res;}
int main() {
ios::sync_with_stdio(false);
cin >> n;
for(int i=1;i<=n;++i){
cin>>a[i];
add(i,a[i]-a[i-1]);
}
for(int i=0;i<n;++i){
int op,l,r,c;
cin>>op>>l>>r>>c;
if(op==0) { add(l,c);add(r+1,-c); }
else cout<<query(r)<<endl;
}
return 0;
}