POJ 3468 (线段树)

和自甴很熟 提交于 2020-03-30 11:45:21

题目链接:http://poj.org/problem?id=3468

You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output
4
55
9
15
Hint
The sums may exceed the range of 32-bit integers.
 
 
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<map>
  7 #include<set>
  8 #include<vector>
  9 using namespace std;
 10 #define ll long long
 11 const int inf=99999999;
 12 const int mod=1e9+7;
 13 const int maxn=100000+10;
 14 typedef struct 
 15 {
 16     int left;
 17     int right;
 18     ll int weight;
 19     ll int lan;
 20 } St;
 21 St tree[maxn<<2];
 22 int n,m;
 23 int a,b;
 24 ll int ans;
 25 ll int num; 
 26 inline void build_tree(int k,int left,int right)//建树 
 27 {
 28     tree[k].left=left;
 29     tree[k].right=right;
 30     if(left==right)
 31     {
 32         cin>>tree[k].weight;
 33         return ;
 34     }
 35     int mid=(left+right)>>1;
 36     build_tree(k<<1,left,mid);//左子树
 37     build_tree(k<<1|1,mid+1,right);//右子树
 38     tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并,该节点权重等于左子树加右子树权重 
 39 }
 40 inline void lan_down(int k)//树懒标记下传 
 41 {
 42     tree[k<<1].lan+=tree[k].lan;
 43     tree[k<<1|1].lan+=tree[k].lan;
 44     tree[k<<1].weight+=tree[k].lan*(tree[k<<1].right-tree[k<<1].left+1);
 45     tree[k<<1|1].weight+=tree[k].lan*(tree[k<<1|1].right-tree[k<<1|1].left+1);
 46     tree[k].lan=0;
 47 }
 48 inline void ask_point(int k)//单点查询 
 49 {
 50     if(tree[k].left==tree[k].right)
 51     {
 52         ans=tree[k].weight;
 53         return ;
 54     }
 55     if(tree[k].lan)
 56         lan_down(k);
 57     int mid=(tree[k].left+tree[k].right)>>1;
 58     if(a<=mid)//a表示单点询问位置
 59         ask_point(k<<1);//目标位置靠左,递归左孩子
 60     else
 61         ask_point(k<<1|1);//目标位置靠右,递归右孩子
 62 }
 63 inline void add_point(int k)//单点修改 
 64 {
 65     if(tree[k].left==tree[k].right)
 66     {
 67         tree[k].weight+=num;//单点增加num 
 68         return ;
 69     }
 70     if(tree[k].lan)//树懒标记下传 
 71         lan_down(k);
 72     int mid=(tree[k].left+tree[k].right)>>1;
 73     if(a<=mid)
 74         add_point(k<<1);
 75     else
 76         add_point(k<<1|1);
 77     tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并 
 78 }
 79 inline void ask_qujian(int k)//区间查询 
 80 {
 81     if(tree[k].left>=a&&tree[k].right<=b)//包含了left,right当前区间,全加上 
 82     {
 83         ans+=tree[k].weight;
 84         return ;
 85     }
 86     if(tree[k].lan)//树懒标记下传 
 87         lan_down(k);
 88     int mid=(tree[k].left+tree[k].right)>>1;
 89     if(a<=mid)//递归查询左子区间 
 90         ask_qujian(k<<1);
 91     if(b>mid)//递归查询右子区间
 92         ask_qujian(k<<1|1);
 93 }
 94 inline void add_qujian(int k)//区间修改 
 95 {
 96     if(tree[k].left>=a&&tree[k].right<=b)
 97     {
 98         tree[k].weight+=num*(tree[k].right-tree[k].left+1);
 99         tree[k].lan+=num;
100         return ;
101     }
102     if(tree[k].lan)
103         lan_down(k);
104     int mid=(tree[k].left+tree[k].right)>>1;
105     if(a<=mid)
106         add_qujian(k<<1);
107     if(b>mid)
108         add_qujian(k<<1|1);
109     tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并 
110 }
111 int main()
112 {
113     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
114     cin>>n>>m; //n个节点,m个操作 
115     build_tree(1,1,n);//建树
116     char op;
117     for(int i=0;i<m;i++)
118     {
119         cin>>op>>a>>b;
120         if(op=='Q')
121         {
122             ans=0;
123             ask_qujian(1);//区间查询
124             cout<<ans<<endl;
125         }
126         else if(op=='C')
127         {
128             cin>>num;
129             add_qujian(1);//区间修改 
130         }
131     }
132     return 0;
133 }

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!