洛谷 P3372 线段树1

这是一道模板题

线段树介绍https://www.cnblogs.com/nvwang123/p/10420832.html

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int m,n;
 4 int a[100001];
 5 
 6 struct node{ 
 7    int l,r;   
 8    long long w,f;  //w是区间值,f是懒标记 
 9 }xds[4*100001];   //4倍空间 
10 
11 //一、建树 
12 void buid(int l,int r,int k){   
13     xds[k].l=l; 
14     xds[k].r=r;
15     if(l==r){
16         xds[k].w=a[l];  // 最底层的区间从左边开始是1,所以可以这样 
17         return;
18     }
19     int m=(l+r)/2;
20     buid(l,m,2*k);
21     buid(m+1,r,2*k+1);
22     xds[k].w=xds[2*k].w+xds[2*k+1].w;//不要忘记区间和上传!!特别容易忘 
23 }
24 
25 
26 //二、懒标记下传 
27 void down(int k){
28     xds[2*k].w+=xds[k].f*(xds[2*k].r-xds[2*k].l+1);
29     xds[2*k+1].w+=xds[k].f*(xds[2*k+1].r-xds[2*k+1].l+1);
30     xds[2*k].f+=xds[k].f;
31     xds[2*k+1].f+=xds[k].f;
32     xds[k].f=0;//易漏 
33     }
34 
35 //三、区间修改    
36 void add_(int x,int y,int k,int a){
37     if(xds[a].l>=x&&xds[a].r<=y){
38         xds[a].w+=(long long)k*(xds[a].r-xds[a].l+1);
39         xds[a].f+=k;  //易漏 ,记得做懒标记 
40         return;
41     }
42     if(xds[a].f) down(a);//!!! 
43     int m=(xds[a].l+xds[a].r)/2;
44     if(x<=m) add_(x,y,k,a*2);
45     if(y>m)  add_(x,y,k,a*2+1);    
46     xds[a].w=xds[a*2].w+xds[a*2+1].w;
47 }
48 
49 long long ask_(int x,int y,int k)  //注意数据范围内,开int只能得70分 
50   {
51       if (xds[k].l>=x&&xds[k].r<=y)
52         return xds[k].w;
53     
54       if(xds[k].f)    down(k);
55       
56       int m=(xds[k].l+xds[k].r)/2;
57     long long ans=0;
58       if(x<=m) ans+=ask_(x,y,k*2);
59     if(y>m)  ans+=ask_(x,y,k*2+1);    
60       return ans;
61   }
62 
63 
64 int main(){
65     cin>>n>>m;
66 
67     for(int i=1;i<=n;i++)   cin>>a[i];
68     buid(1,n,1);    
69 
70     for(int i=1;i<=m;i++){
71         int a,x,y,k;
72         cin>>a;
73         if(a==1)  cin>>x>>y>>k,add_(x,y,k,1);
74         if(a==2)  cin>>x>>y,cout<<ask_(x,y,1)<<endl;
75     }
76     return 0;
77 }

 

上一篇:xds


下一篇:[Vani有约会]雨天的尾巴 - 线段树合并