标签:
输入n和n个数,再输入操作的次数,每次操作的指令为:“1”表示查询,后面输入查询的区间(左右两端点) “2”表示区间增减,后面输入操作的区间(左右两端点)和增加的值(可能为负数)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=1024; 6 int _sum,_max,_min; 7 int addv[maxn*2],sumv[maxn*2],minv[maxn*2],maxv[maxn*2]; 8 int y1,y2,v,ql,qr,n; 9 void cself(int o,int l,int r) 10 { 11 minv[o]=maxv[o]=sumv[o]=0; 12 if(l<r){ 13 minv[o]=min(minv[o*2],minv[o*2+1]); 14 sumv[o]=sumv[o*2]+sumv[o*2+1]; 15 maxv[o]=max(maxv[o*2],maxv[o*2+1]); 16 } 17 minv[o]+=addv[o],maxv[o]+=addv[o],sumv[o]+=(r-l+1)*addv[o]; 18 } 19 void query(int o,int l,int r,int added) 20 { 21 if(ql<=l&&r<=qr){ 22 _sum+=(r-l+1)*added+sumv[o]; 23 _min=min(_min,minv[o]+added); 24 _max=max(_max,maxv[o]+added); 25 }else{ 26 int m=(l+r)/2; 27 if(ql<=m) query(o*2,l,m,added+addv[o]); 28 if(m<qr) query(o*2+1,m+1,r,added+addv[o]); 29 } 30 } 31 void update(int o,int l,int r) 32 { 33 if(y1<=l&&r<=y2){ 34 addv[o]+=v; 35 }else{ 36 int m=(l+r)/2; 37 if(y1<=m) update(o*2,l,m); 38 if(m<y2) update(o*2+1,m+1,r); 39 } 40 cself(o,l,r); 41 } 42 void buildTree() 43 { 44 for(int i=1;i<=n;i++) 45 { 46 scanf("%d",&v); 47 y2=y1=i; 48 update(1,1,n); 49 } 50 } 51 void ansQuestion(int q) 52 { 53 int op; 54 for(int i=1;i<=q;i++) 55 { 56 scanf("%d",&op); 57 if(op==1)//查询 58 { 59 _sum=0; 60 _min=1<<30; 61 _max=-_min; 62 scanf("%d %d",&ql,&qr); 63 int mmin=min(ql,qr); 64 qr=max(ql,qr); 65 ql=mmin; 66 query(1,1,n,0); 67 printf("sum:%d\tmin:%d\tmax:%d\n",_sum,_min,_max); 68 }else if(op==2)//区间增减 69 { 70 scanf("%d %d %d",&y1,&y2,&v); 71 int mmin=min(y1,y2); 72 y2=max(y1,y2); 73 y1=mmin; 74 update(1,1,n); 75 }else printf("Wrong Operator\n"); 76 } 77 } 78 void init() 79 { 80 memset(addv,0,sizeof(addv)); 81 } 82 int main() 83 { 84 int q; 85 init(); 86 scanf("%d",&n); 87 buildTree(); 88 scanf("%d",&q); 89 ansQuestion(q); 90 return 0; 91 }
标签:
原文地址:http://www.cnblogs.com/gzhonghui/p/5803541.html