codevs1082
题目描述 Description
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
输出描述 Output Description
对于每个询问输出一行一个答案
样例输入 Sample Input
3
1
2
3
2
1 2 3 2
2 2 3
样例输出 Sample Output
9
数据范围及提示 Data Size & Hint
数据范围
1<=n<=200000
1<=q<=200000
先给出最基础的线段树的打法
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; int n,Q,a[200005]; inline int read(){ char ch=getchar();int k=0,f=1; while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-'0';ch=getchar();} return k*f; } void add(int x,int add){ for(;x<=n;x+=x&-x) a[x]+=add; } int query(int x){ int k=0;for(;x;x-=x&-x) k+=a[x];return k; } int main(){ n=read(); for(int i=1;i<=n;i++) add(i,read()); Q=read(); for(int i=1;i<=Q;i++){ int flag=read(),x=read(),y=read();if(x>y)swap(x,y); if(flag==1){ int z=read(); add(x,(y-x+1)*z);add(y+1,-(y-x+1)*z); } else printf("%ld\n",query(y)-query(x-1)); } return 0; }
但打这题主要是为了理解树状数组的区间修改和区间查询
#include<cstdio> #include<cctype> using namespace std; long long c1[200004],c2[200004],n,q; inline long long read(){ char ch=getchar();long long k=0; while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-'0';ch=getchar();} return k; } void update(long long *arr,long long x,long long add){ for(;x<=n;x+=x&-x) arr[x]+=add; } long long query(long long *arr,long long x){ long long t=0;for(;x;x-=x&-x) t+=arr[x];return t; } int main(){ n=read();long long las=0; for(long long i=1;i<=n;i++){ long long y=read();update(c1,i,y-las);update(c2,i,(i-1)*(y-las));las=y;//i-1=n-(n-i+1)=>在前缀和中,y-las被加了(n-i+1)次,由于后来统计师算了n次,c[i]记录多算的数的大小 } q=read(); for(long long i=1;i<=q;i++){ long long flag=read(),l=read(),r=read(); if(flag==1){ long long inc=read(); update(c1,l,inc);update(c1,r+1,-inc);//差分思想,c[i]记录差,则segma(c[1]~c[i])为数 i 的值 update(c2,l,(l-1)*inc);update(c2,r+1,-r*inc);//同理 l-1=n-(n-l+1) r=n-(n-(r+1)+1) } else{ long long sum1=(l-1)*query(c1,l-1)-query(c2,l-1); long long sum2=r*query(c1,r)-query(c2,r); printf("%lld\n",sum2-sum1); } } return 0; }