时间限制: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
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
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; }