您的位置:首页 > 其它

蓝桥杯 算法训练 操作格子 (最基本的线段树)

2014-02-26 21:39 267 查看
某渣终于开始写了第一次线段树了,哇咔咔!!!!!!!!!

题目:

算法训练 操作格子

时间限制: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
样例输出
6

3
数据规模与约定

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

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

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

明显的最基本的线段树

随便说一下某渣是看了两篇这题的题解才会做的:

/article/1468453.html

/article/1338285.html

还有HH大神写的一篇线段树完全版的解析

http://www.notonlysuccess.com/index.php/segment-tree-complete/

代码:

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<limits.h>
using namespace std;

struct node
{
int l, r;
int sum, max;
}a[400001];

int Max(int x,int y)
{
return x> y? x: y;
}

void Build(int l,int r, int n)// 构建一颗范围为L-R的线段树
{
a
.l= l;
a
.r= r;
a
. sum= 0;
a
. max= 0;
if(l==r)
return;
Build(l , (l + r) /2 , 2*n);// 构建该结点左子树[1,(l+r)/2]
Build(1+(l+r) /2 , r, 2*n + 1);// 构建该结点右子树[1+(l+r)/2,r]
}

void Change(int n, int v, int num) //改变结点[v,v]的值
{
if(v == a
.l && v== a
.r)
{
a
.sum= num;
a
.max= num;
return;
}
int mid= (a
.l + a
.r) / 2;
if(v <= mid)
Change(2*n, v, num);// 说明结点[V,V]在第n个结点的左子树上
else
Change(1+ 2*n, v, num);// 说明结点[V,V]在第n个结点的右子树上
a
.sum= a[2*n].sum + a[ 1+2*n ].sum; //从下往上更新所有父亲结点的值
a
.max= Max(a[2*n].max,a[ 1+2*n ].max);//从下往上更新所有父亲结点的值
}

int Qsum(int l, int r, int n) //求[l,r]之间权值的和
{
if(l == a
.l && r == a
.r)
return a
.sum;// 说明第n结点刚好为[l,r];
int mid= (a
.l + a
.r)/2;
//printf("%d\n",mid);
if(r<= mid)
return Qsum(l,r,2*n); //情况一:[l,r]全在第n个结点的左子树上
else if(l> mid)
return Qsum(l,r,1+2*n); //	情况二: [l,r]全在第n个结点的右子树上
else
return Qsum(l,mid,2*n) + Qsum(mid+1,r,1+2*n); //情况三:左右子树都占有
}

int Qmax(int l, int r, int n)//求[l,r]之间的最大权值
{
if(l == a
.l && r == a
.r)
return a
.max;
int mid= ( a
.l + a
.r) /2;
if(r<= mid)
return Qmax(l,r,2*n);
else if(l> mid)
return Qmax(l,r,1+2*n);
else
return Max(Qmax(l,mid,2*n), Qmax(mid+1,r,1+2*n));
}

int main()
{
int n,m;
scanf("%d%d",&n,&m);
Build(1,n,1);// 先建一颗1-n的线段树
for(int i= 1; i<= n; i++)
{
int t;
scanf("%d",&t);
Change(1,i,t);
}
while(m--)
{
int x,y,p;
scanf("%d%d%d",&p,&x,&y);
if(p == 1)
Change(1,x,y);
else if(p==2)
{
int sum= Qsum(x,y,1);
printf("%d\n",sum);
}
else
{
int max= Qmax(x,y,1);
printf("%d\n",max);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: