poj3468 A Simple Problem with Integers
给定长度为N的数列A,然后输入M行操作指令。
第一类指令形如“C l r d”,表示把数列中第l~r个数都加d。
第二类指令形如“Q X”,表示询问数列中第x个数的值。
对于每个询问,输出一个整数表示答案。
输入格式
第一行包含两个整数N和M。
第二行包含N个整数A[i]。
接下来M行表示M条指令,每条指令的格式如题目描述所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
1≤N,M≤1051≤N,M≤105,
|d|≤10000|d|≤10000,
|A[i]|≤1000000000|A[i]|≤1000000000
输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2
输出样例:
4
1
2
5
这次用线段树来实现,这里不带lazy标记的话时间复杂度降为O(n)
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ULL; typedef long long ll; #define form(i,n) for(int i=1;i<=n;i++) #define forn(i,n) for(int i=0;i<n;i++) #define mst(a) memset(a,0,sizeof(a)) #define P pair<int,int> #define wh(T) while(T--) const int MAX_N=1e7+10; const int N=1e5+90; const int inf=1e8; const int SIZE=100010; struct SegmentTree{ int l,r; long long sum,add; #define l(x) tree[x].l #define r(x) tree[x].r #define sum(x) tree[x].sum #define add(x) tree[x].add }tree[N*4]; int a[N],n,m; void build(int p,int l,int r)//No.p, [l,r] { l(p)=l,r(p)=r; if(l==r) { sum(p)=a[l]; return; } int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); sum(p)=sum(p*2)+sum(p*2+1); } void spread(int p) { if(add(p)) { sum(p*2)+=add(p)*(r(p*2)-l(p*2)+1); sum(p*2+1)+=add(p)*(r(p*2+1)-l(p*2+1)+1); add(p*2)+=add(p); add(p*2+1)+=add(p); add(p)=0; } } void change(int p,int l,int r,int z) { if(l<=l(p)&&r>=r(p)) { sum(p)+=(long long)z*(r(p)-l(p)+1); add(p)+=z; return; } spread(p); int mid=(l(p)+r(p))/2; if(l<=mid) change(p*2,l,r,z); if(r>mid) change(p*2+1,l,r,z); sum(p)=sum(p*2)+sum(p*2+1); } long long ask(int p,int l,int r) { if(l<=l(p)&&r>=r(p)) return sum(p); spread(p); int mid=(l(p)+r(p))/2; long long ans=0; if(l<=mid) ans+=ask(p*2,l,r); if(r>mid) ans+=ask(p*2+1,l,r); return ans; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(m--) { char op[2]; int x,y,z; scanf("%s%d%d",op,&x,&y); if(op[0]=='C') { scanf("%d",&z); change(1,x,y,z); } else printf("%I64d\n",ask(1,x,y)); } }