试题 算法训练 操作格子

资源限制
时间限制:1.0s   内存限制:256.0MB
 
问题描述

有n个格子,从左到右放成一排,编号为1-n。

共有m次操作,有3种操作类型:

1.修改一个格子的权值,

2.求连续一段格子权值和,

3.求连续一段格子的最大值。

对于每个2、3操作输出你所求出的结果。

输入格式

第一行2个整数n,m。

接下来一行n个整数表示n个格子的初始权值。

接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。

输出格式

有若干行,行数等于p=2或3的操作总数。

每行1个整数,对应了每个p=2或3操作的结果。

样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
 
样例输出
6
3
 
数据规模与约定

对于20%的数据n <= 100,m <= 200。

对于50%的数据n <= 5000,m <= 5000。

对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。

这题考察了线段树-[单点更新 区间查询]的内容,首先要建个线段树,包含区间左右端点、最大值和权值和.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <string>
 6 #include <cmath>
 7 #include <algorithm>
 8 #define INF 0x3f3f3f3f
 9 #define zero 1e-7
10 
11 using namespace std;
12 typedef long long ll;
13 const ll mod=1000000007;
14 const ll max_n=1e5+5;
15 
16 struct tree{
17     int l, r, sum, maxx;
18 }t[max_n<<2];
19 
20 int a[max_n];
21 int n, m;
22 
23 void build(int i, int l, int r) {//节点,区间左端点、右端点 
24     t[i].l=l;
25     t[i].r=r;
26     if(l==r) {
27         t[i].maxx=t[i].sum=a[r];
28         return;
29     }
30     int mid=(l+r)>>1;
31     build(i<<1, l, mid);
32     build(i<<1|1, mid+1, r);
33     t[i].sum=t[i<<1].sum+t[i<<1|1].sum;
34     t[i].maxx=max(t[i<<1].maxx, t[i<<1|1].maxx);
35 }
36 
37 void update(int i, int x, int y) {//节点,要修改的格子编号,新的权值 
38     if(t[i].l==t[i].r) {//找到要修改的格子 
39         t[i].sum=t[i].maxx=y;
40         return;
41     }
42     int mid=(t[i].l+t[i].r)>>1;
43     if(x<=mid) //在该节点的左子节点 
44         update(i<<1, x, y);
45     else //在该节点的右子节点
46         update(i<<1|1, x, y);
47     t[i].sum=t[i<<1].sum+t[i<<1|1].sum;
48     t[i].maxx=max(t[i<<1].maxx, t[i<<1|1].maxx);
49 }
50 
51 int getsum(int i, int x, int y) {
52     if(t[i].l>=x && t[i].r<=y) //该节点所在区间完全被包含在目标区间里面 
53         return t[i].sum;
54     int mid=(t[i].l+t[i].r)>>1;
55     int ans=0;
56     if(x<=mid) ans+=getsum(i<<1, x, y);
57     if(y>mid) ans+=getsum(i<<1|1, x, y);
58     return ans;
59 }
60 
61 int getmax(int i, int x, int y) {
62     if(t[i].l>=x && t[i].r<=y) 
63         return t[i].maxx;
64     int mid=(t[i].l+t[i].r)>>1;
65     int maxy=-1;
66     if(x<=mid) maxy=max(maxy, getmax(i<<1, x, y));
67     if(y>mid) maxy=max(maxy, getmax(i<<1|1, x, y));
68     return maxy;
69 }
70 
71 int main() {
72     cin>>n>>m;
73     for(int i=1; i<=n; i++) {
74         scanf("%d", &a[i]);
75     }
76     build(1, 1, n);//根节点,区间左端点,右端点
77     int p, x, y;
78     for(int i=0; i<m; i++) {
79         scanf("%d %d %d", &p, &x, &y);
80         switch(p) {
81             case 1: update(1, x, y); break;
82             case 2: printf("%d
", getsum(1, x, y)); break;
83             case 3: printf("%d
", getmax(1, x, y)); break;
84             default: break; 
85         }
86     } 
87     return 0;
88 }
原文地址:https://www.cnblogs.com/wwqzbl/p/13533954.html