问题描述

有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. Hadoop安全(2)——————UserGroupInformation

    UserGroupInformation保存hadoop用户及组信息 此类包装JAAS Subject,并提供确定用户的用户名和组的方法.它支持Windows,Unix和Kerberos登录模块.

  2. Linux入门之常用命令(1)

    退出系统 exit 图形界面 startx 时间 date 日历 cal [month] [year] 计算器 bc 帮助 man [command]  // info [command] 在线用户 ...

  3. 为什么ABAP开发者需要使用面向对象技术?

    ABAP对面向对象的支持已有十多年的历史,然而在生产实践中,我们对这门技术的应用十分有限. 一方面,面向过程的惯性长期存在着:另一方面,对于大部分二次开发工作而言,似乎并没有足够的理由促使开发者使用面 ...

  4. Redhat 5上OPENLDAP的安装备份和恢复

    1. 安装 1.1. 安装环境 查看当前操作系统版本: [root@vmw9181-app ~]# cat /etc/issue Red Hat Enterprise Linux Server rel ...

  5. 电脑本机ping通Linux虚拟机的方法

    一.安装VMware: 二.创建Linux虚拟机(centOS7): 三.开启虚拟机,在Linux桌面右键打开终端,输入查看虚拟机ip地址的命令:ifconfig -a    四.打开本机cmd窗口, ...

  6. ZOJ-2091-Mean of Subsequence (反证法的运用!!)

    http://blog.csdn.net/u014355480/article/details/40862041 ZOJ2091 题意:其实就是找后几个数的平均值的最大值!! (贪心策略!要找对) k ...

  7. 启用事务操作,解决批量插入或更新sqlite,mssql等数据库耗时问题

    private void button1_Click(object sender, EventArgs e) { //Sqlite使用事务批量操作 极大的提高速度 DateTime starttime ...

  8. 使用keepalived使用主备热备份功能

    图: 配置文件: 主服务器的配置如下: global_defs { router_id NodeA}vrrp_instance VI_1 { state MASTER #设置为主服务器 interfa ...

  9. Swift搭建服务端

    原文:Hello Server Side Swift 作者:Logan Wright 译者:CocoaChina--kmyhy(博客) 自从苹果官方发布了一个 Swift 的 Linux 开源版本之后 ...

  10. SpringMVC 实现文件的上传与下载

    一  配置SpringMVC ,并导入与文件上传下载有关的jar包(在此不再赘述) 二 新建 相应 jsp 和controller FileUpAndDown.jsp <%@ page lang ...