码迷,mamicode.com
首页 > 其他好文 > 详细

线段树-区间增减

时间:2016-08-24 17:13:59      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:

输入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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!