标签:
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
对于每个询问输出一行一个答案
3
1
2
3
2
1 2 3 2
2 2 3
9
数据范围
1<=n<=200000
1<=q<=200000
代码
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 const int N=200010; 7 ll a[N*4],tag[N*4]; 8 int n,b; 9 ll read(){ 10 register ll f=1,x=0; 11 register char ch=getchar(); 12 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘) f=-1;ch=getchar();} 13 while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar(); 14 return x*f; 15 } 16 void ins(int k,int l,int r,int x,int y){ 17 int mid=(l+r)>>1; 18 if(l==r) {a[k]=y;return;} 19 if(x>mid) ins(k<<1|1,mid+1,r,x,y); 20 else ins(k<<1,l,mid,x,y); 21 a[k]=a[k<<1]+a[k<<1|1]; 22 } 23 void pushdown(int x,int l,int r){ 24 int lc=x<<1,rc=x<<1|1,mid=(l+r)>>1; 25 if(!tag[x]) return; 26 a[lc]+=tag[x]*(mid-l+1); 27 a[rc]+=tag[x]*(r-mid); 28 tag[lc]+=tag[x];tag[rc]+=tag[x];tag[x]=0; 29 } 30 void add(int k,int l,int r,int L,int R,int val){ 31 int mid=(l+r)>>1; 32 if(l==L&&r==R){ 33 tag[k]+=val;a[k]+=val*(R-L+1);return; 34 } 35 pushdown(k,l,r); 36 if(R<=mid) add(k<<1,l,mid,L,R,val); 37 else if(L>mid) add(k<<1|1,mid+1,r,L,R,val); 38 else add(k<<1,l,mid,L,mid,val),add(k<<1|1,mid+1,r,mid+1,R,val); 39 a[k]=a[k<<1]+a[k<<1|1]; 40 } 41 ll query(int k,int l,int r,int L,int R){ 42 int mid=(l+r)>>1; 43 if(l==L&&r==R) return a[k]; 44 pushdown(k,l,r); 45 if(R<=mid) return query(k<<1,l,mid,L,R); 46 else if(L>mid) return query(k<<1|1,mid+1,r,L,R); 47 else return query(k<<1,l,mid,L,mid)+query(k<<1|1,mid+1,r,mid+1,R); 48 } 49 int main(){ 50 n=read(); 51 for(int i=1;i<=n;i++) b=read(),ins(1,1,n,i,b); 52 int q=read(); 53 for(int i=1;i<=q;i++){ 54 int opt=read(); 55 if(opt==1){ 56 int l=read(),r=read(),val=read(); 57 add(1,1,n,l,r,val); 58 } 59 else{ 60 int l=read(),r=read(); 61 printf("%lld\n",query(1,1,n,l,r)); 62 } 63 } 64 return 0; 65 }
标签:
原文地址:http://www.cnblogs.com/shenben/p/5459728.html