问题描述
有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],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列 ...
随机推荐
-
SQL Server 2008 R2数据库镜像部署
概述 “数据库镜像”是一种针对数据库高可用性的基于软件的解决方案.其维护着一个数据库的两个相同的副本,这两个副本分别放置在不同的SQL Server数据库实例中.建议使用不同位置的两台服务器来承载.在 ...
-
iOS中第三方框架刷新
0.先加入主头文件 #import "MJRefresh.h" 1.添加下拉刷新 MJRefreshHeaderView *header = [MJRefreshHeaderVie ...
-
img 元素无法获取高度的问题
项目里有这么一个功能,需要 ajax 从服务器端获取数据,然后本地生成 DOM 结构再 append 到页面上. 其中的图片是直接拿到的图像数据,而不是 url,所以据此生成 dataURI 赋值给 ...
-
Python数据结构之二——tuple(元组)
Python版本:3.6.2 操作系统:Windows 作者:SmallWZQ 列表和元组是Python中最常见的内建序列.元组与列表一样,但是tuple一旦创建就不能修改.创建元组的语法非常简单 ...
-
在TextBox中敲击回车执行ASP.NET后台事件
1.在TextBox中敲击回车执行ASP.NET后台事件 0.说明 页面中有一个用于搜索的TextBox,希望能在输入内容后直接回车开始搜索,而不是手动去点击它旁边的搜索按钮 但因为该TextBo ...
-
【Qt编程】基于QWT的曲线绘制及图例显示操作
在<QWT在QtCreator中的安装与使用>一文中,我们完成了QWT的安装,这篇文章我们讲讲基础曲线的绘制功能. 首先,我们新建一个Qt应用程序,然后一路默认即可.这时,你会发现总共有: ...
-
exit()
exit()通常是用在子程序中用来终结程序用的,使用后程序自动结束,跳回操作系统. exit(0) 表示程序正常退出,exit⑴/exit(-1)表示程序异常退出. exit() 结束当前进程/当前程 ...
-
php过滤html标签截取部分内容
<?php $str = '<span>fdsfsdf</span><a href="#">href</a>'; echo h ...
-
PostgreSQL内存结构图示
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到*页面:PostgreSQL索引页 作者:高健@博客园 luckyjackgao@ ...
-
Swift,简单语法
1.创建变量 var a=0 //变量 let b=0 //常量 let b:String="你好" //:后可以定义类型(变量一旦定义,类型不可改变)(类型不填Swift会自动判 ...