蓝桥杯-算法训练--ALGO-8 操作格子
问题描述
有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 操作格子的更多相关文章
- Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
试题 算法训练 猴子吃包子 问题描述 从前,有一只吃包子很厉害的猴子,它可以吃无数个包子,但是,它吃不同的包子速度也不同:肉包每秒钟吃x个:韭菜包每秒钟吃y个:没有馅的包子每秒钟吃z个:现在有x1个肉 ...
- Java实现蓝桥杯 算法训练 大等于n的最小完全平方数
试题 算法训练 大等于n的最小完全平方数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输出大等于n的最小的完全平方数. 若一个数能表示成某个自然数的平方的形式,则称这个数为完全平 ...
- 蓝桥杯算法训练 java算法 表达式求值
问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例输出 - ...
- 蓝桥杯 算法训练 ALGO-143 字符串变换
算法训练 字符串变换 时间限制:1.0s 内存限制:256.0MB 问题描述 相信经过这个学期的编程训练,大家对于字符串的操作已经掌握的相当熟练了.今天,徐老师想测试一下大家对于字符串操作的掌 ...
- 蓝桥杯 算法训练 ALGO-125 王、后传说
算法训练 王.后传说 时间限制:1.0s 内存限制:256.0MB 问题描述 地球人都知道,在国际象棋中,后如同太阳,光芒四射,威风八面,它能控制横.坚.斜线位置. 看过清宫戏的中国人都知道, ...
- Java实现 蓝桥杯 算法训练 Beaver's Calculator
试题 算法训练 Beaver's Calculator 问题描述 从万能词典来的聪明的海狸已经使我们惊讶了一次.他开发了一种新的计算器,他将此命名为"Beaver's Calculator ...
- Java实现 蓝桥杯 算法训练 Lift and Throw
试题 算法训练 Lift and Throw 问题描述 给定一条标有整点(1, 2, 3, -)的射线. 定义两个点之间的距离为其下标之差的绝对值. Laharl, Etna, Flonne一开始在这 ...
- Java实现 蓝桥杯 算法训练 Remember the A La Mode(暴力)
试题 算法训练 Remember the A La Mode 问题描述 Hugh Samston经营着一个为今年的ICPC世界总决赛的参与者提供甜点的餐饮服务.他将会提供上面有冰激凌的饼片.为了满足不 ...
- Java实现 蓝桥杯 算法训练 删除数组零元素
算法训练 删除数组零元素 时间限制:1.0s 内存限制:512.0MB 提交此题 从键盘读入n个整数放入数组中,编写函数CompactIntegers,删除数组中所有值为0的元素,其后元素向数组首端移 ...
- Java实现 蓝桥杯 算法训练 数字游戏
试题 算法训练 数字游戏 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个1-N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列 ...
随机推荐
- 深入理解计算机系统chapter5
编写高效的程序需要:1.选择合适的数据结构和算法 2.编译器能够有效优化以转换为高效可执行代码的源代码 3.利用并行性 优化编译器的局限性 程序示例: combine3的汇编代码: load-> ...
- 关于Vue问题记录
第一次安装Vue时,npm run dev报错处理 1.如果是报错:提示说没找到test这个文件夹 参考资料:https://segmentfault.com/q/1010000010893904 就 ...
- springmvc 格式化返回日期格式
<mvc:annotation-driven conversion-service="conversionService"> <mvc:message-conve ...
- Ubuntu16.04 Using Note
I meet lots of problems when i installed and use ubuntu 16.04.below is my using note: (my operating ...
- vue学习第一篇 hello world
计划近期开始学习vue.js.先敲一个hello wolrd作为开始. <!DOCTYPE html> <html lang="en"> <head& ...
- P1013
问题 D: P1013 时间限制: 1 Sec 内存限制: 128 MB提交: 33 解决: 21[提交][状态][讨论版] 题目描述 " 找啊找啊找GF,找到一个好GF,吃顿饭啊拉拉手 ...
- AIM Tech Round 4 (Div. 2)ABCD
A. Diversity time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- 从头编写 asp.net core 2.0 web api 基础框架 (1)
工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.Chrome (最好是) 关于.net core或者.net core 2.0的相 ...
- WPF自定义命令和处发命令
接实现ICommand接口的命令.在介绍之前,先看一下ICommand接口的原型: event EventHandler CanExecuteChanged; bool CanExecute(obje ...
- YYHS-NOIP模拟赛-gcd
题解 这道题题解里说用莫比乌斯反演做(我这个蒟蒻怎么会做呢) 但是不会,所以我们另想方法,这里我们用容斥来做 我们先把500000以内的所有质数筛出来 每次读入编号的时候,先把编号对应的这个数分解质因 ...