codevs 1082 线段树练习 3
2017-03-22 20:17
399 查看
1082 线段树练习 3 区间修改,区间查询;
时间限制: 3 s
空间限制: 128000 KB
题目等级 : 大师 Master
给你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
时间限制: 3 s
空间限制: 128000 KB
题目等级 : 大师 Master
给你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
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int sz=200000+50; struct seg_tree{ int l,r; long long sum; long long ax; } t[sz<<2]; int n,a,q,x,y,z; long long v[sz]; void updata(int m){ t[m].sum=t[m<<1].sum+t[m<<1|1].sum; return ; } void build(int m,int ll,int rr){ t[m].l=ll,t[m].r=rr; if(ll==rr) { t[m].sum=v[ll]; return ; } int mid=(ll+rr)>>1; build(m<<1,ll,mid); build(m<<1|1,mid+1,rr); updata(m); } void add(int m,int vv){ t[m].sum+=(t[m].r-t[m].l+1)*vv; t[m].ax+=vv; return ; } void spread(int m){ if(t[m].ax){ add(m<<1,t[m].ax); add(m<<1|1,t[m].ax); t[m].ax=0; //这里要改为0!! 否则用while会死循环 } return ; } long long ask(int m,int ll,int rr){ if(t[m].l>=ll&&t[m].r<=rr) return t[m].sum; int mid=t[m].l+t[m].r>>1; long long ans=0; spread(m); if(mid>=ll) ans+=ask(m<<1,ll,rr); if(mid<rr) ans+=ask(m<<1|1,ll,rr); return ans; } void change(int m,int ll,int rr,int vv){ if(t[m].l>=ll&&t[m].r<=rr) { add(m,vv);return; } int mid=(t[m].l+t[m].r)>>1; spread(m); if(mid>=ll) change(m<<1,ll,rr,vv); if(mid<rr) change(m<<1|1,ll,rr,vv); updata(m); return ; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&v[i]); build(1,1,n); scanf("%d",&q); while(q--){ scanf("%d",&a); if(a==1){ scanf("%d%d%d",&x,&y,&z); change(1,x,y,z); // for(int i=1;i<=n*4;i++) //printf("i= %d t[i].l= %d t[i].r= %d t[i].sum= %d t[i].ax= %d\n",i,t[i].l,t[i].r,t[i].sum,t[i].ax); } else scanf("%d%d",&x,&y),printf("%lld\n",ask(1,x,y)); } return 0; }
相关文章推荐
- <线段树系列3> codevs 1082 线段树练习3
- codevs 1082 线段树练习3 模板题
- 【codevs 1080~1082】线段树练习重做
- 【codevs 1080~1082】线段树练习重做
- [Codevs] 1082 线段树练习3
- codevs 1082 线段树练习3
- [CodeVS1082] 线段树练习3(区间修改+询问区间和)
- codevs 1082 线段树练习 3
- [CODEVS1082]线段树练习 3
- Codevs1082 线段树练习 3 Lazy
- codevs 1082 线段树练习 3(区间维护)
- COdeVS——T 1082 线段树练习 3 (分块练习)
- Code Vs 1082 线段树练习 3
- 【codevs1082】线段树练习3 线段树
- codevs 1082 线段树练习 3 区间更新+延迟标记
- 【codevs1082】线段树练习 3
- CODE[VS] 1082 线段树练习 3 (区间修改、区间求和)
- Codevs1082 线段树练习三(树状数组)
- [树状数组]code[vs] 1082——线段树练习 3
- 【CODE[VS]】1082 线段树练习 3 树状数组