codevs 1082 线段树练习 3
Posted Nico&11101001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 1082 线段树练习 3相关的知识,希望对你有一定的参考价值。
1082 线段树练习 3
时间限制: 3 s
空间限制: 128000 KB
题目等级 : 大师 Master
题目描述 Description
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
输入描述
Input Description
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
输出描述
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
这题需要开long long,函数也要开!坑
1 //s d s 2 #include<cstdio> 3 #include<iostream> 4 #include<cstdlib> 5 using namespace std; 6 const int N=5000006; 7 long long a[N],sum[N];int miku[N]; 8 long long b,c,d,e; 9 10 void update(int rt) 11 { 12 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 13 } 14 15 void build(int l,int r,int rt) 16 { 17 if(l==r) 18 { 19 sum[rt]=a[l]; 20 return ; 21 } 22 int m=(l+r)>>1; 23 build(l,m,rt<<1); 24 build(m+1,r,rt<<1|1); 25 update(rt); 26 } 27 28 void midify_interval(int l,int r,int rt,int nowl,int nowr,int neww) 29 { 30 if(nowl==l&&nowr==r) 31 { 32 miku[rt]+=neww; 33 sum[rt]+=neww*(r-l+1); 34 return ; 35 } 36 int m=(l+r)>>1; 37 sum[rt<<1]+=miku[rt]*(m-l+1); 38 sum[rt<<1|1]+=miku[rt]*(r-m); 39 miku[rt<<1]+=miku[rt]; 40 miku[rt<<1|1]+=miku[rt]; 41 miku[rt]=0; 42 if(nowr<=m) midify_interval(l,m,rt<<1,nowl,nowr,neww); 43 else if(nowl>m) midify_interval(m+1,r,rt<<1|1,nowl,nowr,neww); 44 else 45 { 46 midify_interval(l,m,rt<<1,nowl,m,neww); 47 midify_interval(m+1,r,rt<<1|1,m+1,nowr,neww); 48 } 49 update(rt); 50 } 51 52 long long query(int l,int r,int rt,int nowl,int nowr) 53 { 54 if(nowl<=l&&nowr>=r) 55 { 56 return sum[rt]; 57 } 58 int m=(r+l)>>1; 59 sum[rt<<1]+=miku[rt]*(m-l+1); 60 sum[rt<<1|1]+=miku[rt]*(r-m); 61 miku[rt<<1]+=miku[rt]; 62 miku[rt<<1|1]+=miku[rt]; 63 miku[rt]=0; 64 long long ans=0; 65 if(nowl<=m) ans+=query(l,m,rt<<1,nowl,nowr); 66 if(nowr>m)ans+=query(m+1,r,rt<<1|1,nowl,nowr); 67 return ans; 68 } 69 70 71 72 int main() 73 { 74 int n; 75 scanf("%lld",&n); 76 for(int i=1;i<=n;i++)scanf("%lld",a+i); 77 build(1,n,1); 78 int m; 79 scanf("%lld",&m); 80 81 for(int i=1;i<=m;i++) 82 { 83 scanf("%lld",&b); 84 if(b==1) 85 { 86 scanf("%lld%lld%lld",&c,&d,&e); 87 midify_interval(1,n,1,c,d,e); 88 } 89 if(b==2) 90 { 91 scanf("%lld%lld",&c,&d); 92 printf("%lld\n",query(1,n,1,c,d)); 93 } 94 } 95 return 0; 96 97 }
以上是关于codevs 1082 线段树练习 3的主要内容,如果未能解决你的问题,请参考以下文章