算法训练 操作格子
时间限制:1.0s 内存限制:256.0MB
锦囊1
使用线段树。
锦囊2
线段树的每个结点记录下这一段区间所有数的和以及最大值即可。
锦囊3
问题描述
有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。
解析:利用线段树解决问题
#include<stdio.h>
#include<stdlib.h>
#define N 100000
int w[N+10];
typedef struct Node{
struct Node *lc,*rc;
int left,right;//左右区间端点
int max;//对应区间最大值
int sum;//对应区间元素和
}tree,*Interval_tree;
void Build(Interval_tree &T,int left,int right)
{
//构建线段树
int mid;
T=(Interval_tree)malloc(sizeof(tree));
T->lc=NULL;
T->rc=NULL;
T->left=left;
T->right=right;
if(left==right)
{
T->sum=w[left];
T->max=w[left];
return ;//递归出口
}//if
mid=(left+right)>>1;
Build(T->lc,left,mid);
Build(T->rc,mid+1,right);
T->sum=T->lc->sum+T->rc->sum;
T->max=T->lc->max>T->rc->max?T->lc->max:T->rc->max;
}
int query_sum(Interval_tree &T,int x,int y)
{
int mid=(T->left+T->right)>>1;
if(T->left==x&&T->right==y)
{
return T->sum;
}
if(mid+1<=x)
return query_sum(T->rc,x,y);
if(mid>=y)
return query_sum(T->lc,x,y);
return query_sum(T->lc,x,mid)+query_sum(T->rc,mid+1,y);
}//
int query_max(Interval_tree &T,int x,int y)
{
int mid;
if(T->left==x&&T->right==y)
return T->max;
mid=(T->left+T->right)>>1;
if(mid+1<=x)
return query_max(T->rc,x,y);
if(mid>=y)
return query_max(T->lc,x,y);
return query_max(T->lc,x,mid)>query_max(T->rc,mid+1,y)?query_max(T->lc,x,mid):query_max(T->rc,mid+1,y);
}//
void update(Interval_tree &T,int x,int y)
{
int mid;
if(T->left==x&&T->right==x)
{
T->sum=y;
T->max=y;
return;
}
mid=(T->left+T->right)>>1;
if(x<=mid)
{
update(T->lc,x,y);
}
if(x>=mid+1)
{
update(T->rc,x,y);
}
T->sum=T->lc->sum+T->rc->sum;
T->max=T->lc->max>T->rc->max?T->lc->max:T->rc->max;
}
void ftree(Interval_tree &T)
{
if(T!=NULL)
{
if(T->lc!=NULL)
free(T->lc);
if(T->rc!=NULL)
free(T->rc);
free(T);
}
}
int main()
{
int n,m,i;
int a,x,y;
Interval_tree T;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&w[i]);
}//for
Build(T,1,n);
while(m--)
{
scanf("%d%d%d",&a,&x,&y);
switch(a){
case 1:
update(T,x,y);//修改格子x的权值为y
break;
case 2:
printf("%d\n",query_sum(T,x,y));//求区间[x,y]内格子权值和
break;
case 3:
printf("%d\n",query_max(T,x,y));//求区间[x,y]内格子最大的权值
break;
}//swith
}//whlie
ftree(T);//释放空间
//system("pause");
return 0;
}