题目就是让你维护一个序列的区间加,单点查询.
特别水,数据卡不掉线段树.
不过我相信线段树不会比树状数组好写的.
可是树状数组只能维护单点修改,区间查询啊.
那我们可以把这两个问题转化一下.
通过差分,我们可以将一个数组c表示c[i]=a[i]-a[i-1].
那么我们区间修改就只需要修改两个点就可以了,就转化成了单点修改.
与此同时,我们可以发现,原来的a[i]就等于c[1]+c[2]+...+c[i].
那么我们就可以用树状数组维护区间查询.
好像这就可以转化过来了.
AC代码如下:
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<iostream> using namespace std; int a; int n,m; class tree{ public: long long c[500001]; inline void clear(){ for (int i=0;i<=500000;i++) c[i]=0; } inline int lowbit(int x){ return x&-x; } inline void add(int x,long long num,int n){ while (x<=n){ c[x]+=num; x+=lowbit(x); } } inline long long query(int r){ long long sum=0; while (r){ sum+=c[r]; r-=lowbit(r); } return sum; } }; tree tr; inline long long read(){ int x=0; long long c; bool b=0; for (c=getchar();c<'0'||c>'9';c=getchar()) if (c=='-') b=1; for (;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+c-'0'; if (b) return (-x); else return x; } inline void into(){ int last=0; n=read();m=read(); tr.clear(); for (int i=1;i<=n;i++){ a=read(); tr.add(i,a-last,n); last=a; } } inline void work(){ int c,x,y; long long k; for (int i=1;i<=m;i++){ c=read(); if (c==1) { x=read();y=read();k=read(); tr.add(x,k,n); tr.add(y+1,-k,n); }else { x=read(); printf("%lld\n",tr.query(x)); } } } inline void outo(){ } int main(){ for (int i=1;i<=1;i++){ into(); work(); outo(); } return 0; }