问题描述

有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

用线段树来解题,一开始的时候结点空间开小了= =

因为N个格子,用线段树的话一共会有2*N-1个结点,所以我不小心就开了2*N-1个结点的空间

结果。。。一半超时。。

修改后发现还是有一个用例超时,上代码:

#include<stdio.h>
#include<iostream>
using namespace std;
const int MAX_N = ;
#define max(a,b) a>b?a:b
struct NODE{
int left; //左子树
int right; //右子树
int totalValue; //总和
int maxValue; //最大值
}node[ * MAX_N];
int nodeValue[MAX_N];
//建树
void buildTree(int i, int left, int right){
node[i].left = left;
node[i].right = right;
if (left == right){
node[i].maxValue = nodeValue[left];
node[i].totalValue = nodeValue[left];
}
else{
buildTree( * i, left, (left + right) / );
buildTree( * i + , (left + right) / + , right);
node[i].maxValue = node[ * i].maxValue > node[ * i + ].maxValue ? node[ * i].maxValue : node[ * i + ].maxValue;
node[i].totalValue = node[ * i].totalValue + node[ * i + ].totalValue;
}
} //区间更新
void upDate(int i, int x, int changedX){
if (node[i].left == node[i].right){
node[i].maxValue = changedX;
node[i].totalValue = changedX;
}
else{
if (x <= (node[i].left + node[i].right) / )
upDate( * i, x, changedX);
else if (x >= (node[i].left + node[i].right) / )
upDate( * i + , x, changedX);
node[i].maxValue = node[ * i].maxValue > node[ * i + ].maxValue ? node[ * i].maxValue : node[ * i + ].maxValue;
node[i].totalValue = node[ * i].totalValue + node[ * i + ].totalValue;
}
} //查找区间最大值
//i表示node[i]结点,left,right表示查找范围
int findMax(int i, int left, int right){ int maxValue = -;
if (node[i].left == left && node[i].right == right){ //完全重合
maxValue = max(maxValue, node[i].maxValue);
return maxValue;
}
if (left <= node[ * i].right){ //范围跟node[i]的左子树有交集
if (right <= node[ * i].right){
maxValue = max(maxValue, findMax( * i, left, right));
}
else{
maxValue = max(maxValue, findMax( * i, left, node[ * i].right));
}
}
if (right >= node[ * i + ].left){ //范围跟node[i]的右子树有交集
if (left >= node[ * i + ].left){ //被右子树完全包含
maxValue = max(maxValue, findMax( * i + , left, right));
}
else{
maxValue = max(maxValue, findMax( * i + , node[ * i + ].left, right));
}
}
return maxValue;
} //查找区间数值之和
int findTotal(int i, int left, int right){
int total = ;
if (node[i].left == left && node[i].right == right){
total = node[i].totalValue;
return total;
} if (left <= node[ * i].right){
if (right <= node[ * i].right){
total = findTotal( * i, left, right);
}
else{
total += findTotal( * i, left, node[ * i].right);
}
}
if (right >= node[ * i + ].left){
if (left >= node[ * i + ].left){
total = findTotal( * i + , left, right);
}
else{
total += findTotal( * i + , node[ * i + ].left, right);
}
} return total;
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++)
scanf("%d", &nodeValue[i]);
buildTree(, , n); for (int j = ; j <= m; j++){
int workIndex, x, y;
scanf("%d%d%d", &workIndex, &x, &y);
switch (workIndex){
case :
upDate(, x, y);
break;
case :
printf("%d\n", findTotal(, x, y));
break;
case :
printf("%d\n", findMax(, x, y));
break;
}
}

然后我修改了一下,不要在每一个查找区间数值方法里面比较最大值和总和,而是在left == right的时候才比较最大值和总和。

AC代码:

#include<stdio.h>
#include<iostream>
using namespace std;
const int MAX_N = ;
#define max(a,b) a>b?a:b
struct NODE{
int left; //左子树
int right; //右子树
int totalValue; //总和
int maxValue; //最大值
}node[ * MAX_N];
int nodeValue[MAX_N]; int maxValue = -;
int totalValue = ;
//建树
void buildTree(int i, int left, int right){
node[i].left = left;
node[i].right = right;
if (left == right){
node[i].maxValue = nodeValue[left];
node[i].totalValue = nodeValue[left];
}
else{
buildTree( * i, left, (left + right) / );
buildTree( * i + , (left + right) / + , right);
node[i].maxValue = node[ * i].maxValue > node[ * i + ].maxValue ? node[ * i].maxValue : node[ * i + ].maxValue;
node[i].totalValue = node[ * i].totalValue + node[ * i + ].totalValue;
}
} //区间更新
void upDate(int i, int x, int changedX){
if (node[i].left == node[i].right){
node[i].maxValue = changedX;
node[i].totalValue = changedX;
}
else{
if (x <= (node[i].left + node[i].right) / )
upDate( * i, x, changedX);
else if (x >= (node[i].left + node[i].right) / )
upDate( * i + , x, changedX);
node[i].maxValue = node[ * i].maxValue > node[ * i + ].maxValue ? node[ * i].maxValue : node[ * i + ].maxValue;
node[i].totalValue = node[ * i].totalValue + node[ * i + ].totalValue;
}
} //查找区间最大值
//i表示node[i]结点,left,right表示查找范围
void findMax(int i, int left, int right){ if (node[i].left == left && node[i].right == right){ //完全重合
maxValue = max(maxValue, node[i].maxValue);
return;
}
if (left <= node[ * i].right){ //范围跟node[i]的左子树有交集
if (right <= node[ * i].right){
findMax( * i, left, right);
}
else{
findMax( * i, left, node[ * i].right);
}
}
if (right >= node[ * i + ].left){ //范围跟node[i]的右子树有交集
if (left >= node[ * i + ].left){ //被右子树完全包含
findMax( * i + , left, right);
}
else{
maxValue, findMax( * i + , node[ * i + ].left, right);
}
}
} //查找区间数值之和
void findTotal(int i, int left, int right){
if (node[i].left == left && node[i].right == right){
totalValue += node[i].totalValue;
return;
} if (left <= node[ * i].right){
if (right <= node[ * i].right){
findTotal( * i, left, right);
}
else{
findTotal( * i, left, node[ * i].right);
}
}
if (right >= node[ * i + ].left){
if (left >= node[ * i + ].left){
findTotal( * i + , left, right);
}
else{
findTotal( * i + , node[ * i + ].left, right);
}
}
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++)
scanf("%d", &nodeValue[i]);
buildTree(, , n); for (int j = ; j <= m; j++){
int workIndex, x, y;
scanf("%d%d%d", &workIndex, &x, &y);
switch (workIndex){
case :
upDate(, x, y);
break;
case :
findTotal(, x, y);
printf("%d\n", totalValue);
totalValue = ;
break;
case :
findMax(, x, y);
printf("%d\n", maxValue);
maxValue = -;
break;
}
} /*
for(int j = 1;j<=2*n-1;j++){
cout<<"left: "<<node[j].left<<endl;
cout<<"right: "<<node[j].right<<endl;
cout<<"maxValue: "<<node[j].maxValue<<endl;
cout<<"totalValue: "<<node[j].totalValue<<endl;
}
*/
/*
cout<<"1 到 4号格子最大值: "<<findMax(1,1,4)<<endl;
cout<<"1 到 2号格子最大值: "<<findMax(1,1,2)<<endl;
cout<<"1 到 3号格子最大值: "<<findMax(1,1,3)<<endl;
cout<<"2 到 4号格子最大值: "<<findMax(1,2,4)<<endl;
cout<<"2 到 3号格子最大值: "<<findMax(1,2,3)<<endl;
cout<<"3 到 4号格子最大值: "<<findMax(1,3,4)<<endl; cout<<"1 到 4号格子权值和: "<<findTotal(1,1,4)<<endl;
cout<<"1 到 2号格子权值和: "<<findTotal(1,1,2)<<endl;
cout<<"1 到 3号格子权值和: "<<findTotal(1,1,3)<<endl;
cout<<"2 到 4号格子权值和: "<<findTotal(1,2,4)<<endl;
cout<<"2 到 3号格子权值和: "<<findTotal(1,2,3)<<endl;
cout<<"3 到 4号格子权值和: "<<findTotal(1,3,4)<<endl;
*/
}

蓝桥杯-算法训练--ALGO-8 操作格子的更多相关文章

  1. Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)

    试题 算法训练 猴子吃包子 问题描述 从前,有一只吃包子很厉害的猴子,它可以吃无数个包子,但是,它吃不同的包子速度也不同:肉包每秒钟吃x个:韭菜包每秒钟吃y个:没有馅的包子每秒钟吃z个:现在有x1个肉 ...

  2. Java实现蓝桥杯 算法训练 大等于n的最小完全平方数

    试题 算法训练 大等于n的最小完全平方数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输出大等于n的最小的完全平方数. 若一个数能表示成某个自然数的平方的形式,则称这个数为完全平 ...

  3. 蓝桥杯算法训练 java算法 表达式求值

    问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例输出 - ...

  4. 蓝桥杯 算法训练 ALGO-143 字符串变换

    算法训练 字符串变换   时间限制:1.0s   内存限制:256.0MB 问题描述 相信经过这个学期的编程训练,大家对于字符串的操作已经掌握的相当熟练了.今天,徐老师想测试一下大家对于字符串操作的掌 ...

  5. 蓝桥杯 算法训练 ALGO-125 王、后传说

    算法训练 王.后传说   时间限制:1.0s   内存限制:256.0MB 问题描述 地球人都知道,在国际象棋中,后如同太阳,光芒四射,威风八面,它能控制横.坚.斜线位置. 看过清宫戏的中国人都知道, ...

  6. Java实现 蓝桥杯 算法训练 Beaver's Calculator

    试题 算法训练 Beaver's Calculator 问题描述 从万能词典来的聪明的海狸已经使我们惊讶了一次.他开发了一种新的计算器,他将此命名为"Beaver's Calculator ...

  7. Java实现 蓝桥杯 算法训练 Lift and Throw

    试题 算法训练 Lift and Throw 问题描述 给定一条标有整点(1, 2, 3, -)的射线. 定义两个点之间的距离为其下标之差的绝对值. Laharl, Etna, Flonne一开始在这 ...

  8. Java实现 蓝桥杯 算法训练 Remember the A La Mode(暴力)

    试题 算法训练 Remember the A La Mode 问题描述 Hugh Samston经营着一个为今年的ICPC世界总决赛的参与者提供甜点的餐饮服务.他将会提供上面有冰激凌的饼片.为了满足不 ...

  9. Java实现 蓝桥杯 算法训练 删除数组零元素

    算法训练 删除数组零元素 时间限制:1.0s 内存限制:512.0MB 提交此题 从键盘读入n个整数放入数组中,编写函数CompactIntegers,删除数组中所有值为0的元素,其后元素向数组首端移 ...

  10. Java实现 蓝桥杯 算法训练 数字游戏

    试题 算法训练 数字游戏 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个1-N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列 ...

随机推荐

  1. 使用STS时遇到的小“麻烦”

    背景 今天尝试着用STS(Spring Tool Suite)建立了一个Maven webapp来做一个SpringMVC的小demo,在使用的过程中就遇到了一些小麻烦!!记录在此的目的,其一是为了自 ...

  2. iOS连续dismiss几个ViewController的方法

    原文链接:http://blog.csdn.net/longshihua/article/details/51282388 presentViewController是经常会用到的展现ViewCont ...

  3. Writing Science 笔记 6.20

    1.写作的六个要素:S: Simple 简单的 U: Unexpected 出人意料的 C: Concrete 具体的  C: Credible 可信的  E: Emotional S: Storie ...

  4. EOutOfResources字符异常

    近日,用Delphi编程时,遇到一个莫名其妙的异常:EOutOfResources,这是一个可以重复再现的异常.开始以为是程序中创建的对象太多,导致占用了过多的资源,引起了这个异常.于是在代码中将许多 ...

  5. 【转】Keberos认证原理

    前几天在给人解释Windows是如何通过Kerberos进行Authentication的时候,讲了半天也别把那位老兄讲明白,还差点把自己给绕进去.后来想想原因有以下两点:对于一个没有完全不了解Ker ...

  6. 关于JetBrains CLion 激活 (CLion License Activation)的解决办法,带hosts详细修改

    CLion版本号:JetBrains CLion 2017.2.1 第一行选择Activite,第二行Activate license with:选择Activation code. 这个时候里面的代 ...

  7. Suneast & Daxia (规律)

    Suneast & Daxia Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u ...

  8. poj2823一道纯单调队列

    Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 32099   Accepted: 9526 ...

  9. Iframe刷新页面

    window.parent.frames["name"].location="url";

  10. Ubuntu 16.04源码编译安装nginx 1.10.0

    一.下载相关的依赖库 pcre 下载地址 http://120.52.73.43/jaist.dl.sourceforge.net/project/pcre/pcre/8.38/pcre-8.38.t ...