算法训练 操作格子

时间限制: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<cstdio>
 2 #include<iostream>
 3 #define e tree[id]
 4 #define lson tree[id*2]
 5 #define rson tree[id*2+1]
 6 #define maxn 100005
 7 #define INT 100000000
 8 int A[maxn];
 9 struct Tree{
10     int le,ri,v,s;
11 }tree[4*maxn];
12 int max(int a, int b){ return a>b?a:b; }
13 void pushup(int id){ e.v = max(lson.v,rson.v); e.s = lson.s+rson.s; }
14 void Build_tree(int id,int le,int ri)
15 {
16     e.le = le , e.ri = ri;
17     if(le == ri){ e.v = A[le]; e.s = A[le];    return ; }
18     int mid = (le+ri)/2;
19     Build_tree(id*2,le,mid);
20     Build_tree(id*2+1,mid+1,ri);
21     pushup(id);
22 }
23 int Query1(int id,int x,int y)
24 {
25     int le=e.le,ri=e.ri;
26     if(x<=le && ri<=y) return e.v;
27     int mid=(le+ri)/2;
28     int ret=-INT;
29     if(x<=mid) ret=max(ret,Query1(id*2,x,y));
30     if(y>mid) ret=max(ret,Query1(id*2+1,x,y));
31     return ret;
32 }
33 long long  Query2(int id,int x,int y)
34 {
35     int le=e.le,ri=e.ri;
36     if(x<=le && ri<=y) return e.s;
37     int mid = (le+ri)/2;
38     if(x<=mid && y>mid)  return Query2(id*2,x,y)+Query2(id*2+1,x,y);
39     else if(x<=mid) return Query2(id*2,x,y);
40     else return Query2(id*2+1,x,y);
41 }
42 void Update(int id,int k,int v)
43 {
44     int le=e.le,ri=e.ri;
45     if(le == ri){ e.v=v ; e.s = v; return ;}
46     int mid=(le+ri)/2;
47     if(k<=mid) Update(id*2,k,v);
48     else Update(id*2+1,k,v);
49     pushup(id);
50 }
51 int main(void){
52     int n,m,ans;
53     scanf("%d%d",&n,&m);
54     for(int i=1;i<=n;i++) scanf("%d",&A[i]);
55     Build_tree(1,1,n);
56     for(int i=1;i<=m;i++)
57     {
58         int p,x,y;
59         scanf("%d%d%d",&p,&x,&y);
60         switch(p)
61         {
62             case 1:
63                 Update(1,x,y);
64                 break;
65             case 2:
66                 ans=Query2(1,x,y);
67                 printf("%lld
",ans);
68                 break;
69             case 3:    
70                 ans=Query1(1,x,y);
71                 printf("%d
",ans);
72                 break;
73         }
74     }
75 }
//没有使用宏定义的方法
#include<cstdio> #define maxn 100010 #define INT 100000000 using namespace std; int A[maxn]; struct Tree{ int le,ri,v,s; }tree[4*maxn]; int mymax(int a,int b){ return a>b?a:b;} void Pushup(int id) { tree[id].v=mymax(tree[id*2].v,tree[id*2+1].v); tree[id].s=tree[id*2].s+tree[id*2+1].s; return ; } void Update(int id,int k,int v) { int le=tree[id].le,ri=tree[id].ri; if(le==ri){ tree[id].v=v; tree[id].s=v; return ; } int mid=(le+ri)/2; if(k<=mid) Update(id*2,k,v); else Update(id*2+1,k,v); Pushup(id); } void Build_tree(int id,int x,int y) { tree[id].le=x,tree[id].ri=y; if(x==y){ tree[id].v=A[x]; tree[id].s=A[x]; return; } int mid=(x+y)/2; Build_tree(id*2,x,mid); Build_tree(id*2+1,mid+1,y); Pushup(id); } int Query_1(int id,int x,int y) { int le=tree[id].le,ri=tree[id].ri; if(x<=le && ri<=y) return tree[id].v; int mid = (le+ri)/2; int ret=-INT; if(x<=mid) ret=mymax(ret,Query_1(id*2,x,y)); if(y>mid) ret=mymax(ret,Query_1(id*2+1,x,y)); return ret; } long long Query_2(int id,int x,int y) { int le=tree[id].le,ri=tree[id].ri; if(x<=le && ri<=y) return tree[id].s; int mid=(le+ri)/2; if(x<=mid && y>mid) return Query_2(id*2,x,y)+Query_2(id*2+1,x,y); else if(x<=mid) return Query_2(id*2,x,y); else return Query_2(id*2+1,x,y); } int main(void) { int n,m,sum,max; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&A[i]); Build_tree(1,1,n); for(int i=1;i<=m;i++) { int p,x,y; scanf("%d%d%d",&p,&x,&y); switch(p) { case 1: Update(1,x,y); break; case 2: sum=Query_2(1,x,y); printf("%lld ",sum); break; case 3: max=Query_1(1,x,y); printf("%lld ",max); break; } } return 0; }
原文地址:https://www.cnblogs.com/zuimeiyujianni/p/8631365.html