操作格子(蓝桥杯)

问题描述

有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个数分成根号n个区间,用一个数组保存这个区间的和,

再用一个数组保存这个区间的最大值,当改变一个数的值的时候,要把这个数所在

区间的和与这个区间的最大值更新,查询时,最好分成两种情况,就是y-x<=根号n

    和y-x>根号n两种,第一种直接长度不长,直接循环,第二种分为中间区间模块和两边

之和。

#include<stdio.h>
#include<iostream>
#include<cmath>
using namespace std;

int a[100010]={0};     //保存输入数组
int add[100010]={0};   //保存每个区间的和
int ma[10010]={0};    //保存每个区间的最大值
int k,n,m;

void init()          //把n个数组分为根号n个区间,并求出每个区间的和与最大值
{
	int s=0,j=0,m1=0;
	for(int i=1;i<=n;i++)
	{
		s+=a[i];
		if(a[i]>m1)
			m1=a[i];
		if(i%k==0)
		{
			add[j]=s;
			ma[j]=m1;
			m1=0;
			s=0;
			j++;
		}
	}
}

void bb1(int q,int w)      //改变一个数的值,先找出这个数所在区间,更新这个区间的和与最大值并且更新这个数
{
	int j=(q-1)/k;
	add[j]=add[j]+w-a[q];
	if(ma[j]==a[q])
	{
		a[q]=w;
		int s=0;
		for(int i=j*k+1;i<=(j+1)*k;i++)
		{
			if(a[i]>s)
				s=a[i];
		}
		ma[j]=s;
	}
	else if(ma[j]<w)
		ma[j]=w;
	a[q]=w;
}

int bb2(int q,int w)      //求q-w区间的和
{
	int s=0;
	if(w-q<=k)       //长度不大,直接循环
	{
		for(int i=q;i<=w;i++)
			s+=a[i];
	}
	else
	{
		for(int i=(q-1)/k+1;i<(w-1)/k;i++)     //先求q-w中间的大区间,再加两边
			s+=add[i];
		for(int i=q;i<=((q-1)/k+1)*k;i++)
			s+=a[i];
		for(int i=((w-1)/k)*k+1;i<=w;i++)
			s+=a[i];
	}
	return s;
}

int bb3(int b,int c)       //求b-c区间最大值,与bb2()函数同理
{
	int q=0;
	if(c-b<=k)
	{
		for(int i=b;i<=c;i++)
			if(a[i]>q)
				q=a[i];
	}
	else
	{
		for(int i=(b-1)/k+1;i<(c-1)/k;i++)
		{
			if(ma[i]>q)
				q=ma[i];
		}
		for(int i=b;i<=((b-1)/k+1)*k;i++)
		{
			if(a[i]>q)
				q=a[i];
		}
		for(int i=((c-1)/k)*k+1;i<=c;i++)
		{
			if(a[i]>q)
				q=a[i];
		}
	}

	return q;
}

int main()
{
	cin>>n>>m;
	k=sqrt(n);
	for(int i=1;i<=n;i++)
		cin>>a[i];
	init();
	for(int i=0;i<m;i++)
	{
		int b,c,d;
		cin>>b>>c>>d;
		if(b==1)
			bb1(c,d);
		else if(b==2)
		{
			int s=bb2(c,d);
			printf("%d\n",s);
		}
		else
		{
			int s=bb3(c,d);
			printf("%d\n",s);
		}
	}
	return 0;
}

  

哈哈,英语水平有限,调用函数名字就咋方便咋写了

时间: 2024-10-25 17:47:16

操作格子(蓝桥杯)的相关文章

蓝桥杯 - 操作格子 (线段树)

题目传送:操作格子 思路:简单线段树,单点更新,区间求和以及最值 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map>

【蓝桥杯】操作格子

问题描述 有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

蓝桥杯《操作格子》

解题过程:题意通俗易懂,看完题目以为是普通的对数组进行操作的题目,但是看到输入的数据范围后,发现并不是.但是因为没有好的想法,只能用最简单的方式做,毫无意外的超时了.然后找到这篇博文:http://blog.csdn.net/qq_33245342/article/details/54892576 问题描述  有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个格子的权值, 2.求连续一段格子权值和, 3.求连续一段格子的最大值. 对于每个2.3操作输出你所

蓝桥杯 算法训练 操作格子 [ 线段树 ]

传送门 算法训练 操作格子 时间限制: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

2015 蓝桥杯:4.格子中输出

*/--> pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;}

java算法 蓝桥杯 格子位置

问题描述 输入三个自然数N,i,j (1<=i<=N,1<=j<=N),输出在一个N*N格的棋盘中,与格子(i,j)同行.同列.同一对角线的所有格子的位置. 输入格式 输入共三行,分别输入自然数N,i,j.其中保证N<=24且1<=i<=N,1<=j<=N. 输出格式 输出共四行.第一行为与格子(i,j)同行的所有格子的位置,第二行为与格子(i,j)同列的所有格子的位置,第三行为从左上到右下对角线上的格子的位置,第四行为从左下到右上对角线上的格子的位置

第三届蓝桥杯 c/c++真题

第三届蓝桥杯真题 c/c++ 以下题目我自己也并不是所有的题目都是一次性就能做对或是有结题思路的.有些题目也是经过查证网上相关的资料或是参考了别人的代码和解题思路才做出来的.总的来看,这份题目考了很多循环的只是,还有模拟,动态规划的只是. 其中做题过程中,也有了一些新的体会.起初做代码填空题的时候我没办法知道自己做的是对还是错,就跑到网上查答案,后来发现,题目已经给出了代码,起始我们可以自己加上头文件,然后把空缺的代码加上进行调试的,这样就可以验证自己补充的代码是否正确了. 此外在进行调试的时候

算法-蓝桥杯习题(七)

蓝桥杯习题 蓝桥杯练习系统习题加答案,总共分为6部分,90%习题使用C语言解答,部分使用C++或者Java.大部分习题为搜索参考或者别人提供所得,不足之处在所难免,恳请批评指正(预计200多题,习题仅供学习交流) 目录 算法训练(详见 算法-蓝桥杯习题(一))Go 算法训练(详见 算法-蓝桥杯习题(二))Go 算法提高(waiting...) 历届试题(详见 算法-蓝桥杯习题(六))Go 历届试题(详见 算法-蓝桥杯习题(七))Go 蓝桥杯练习系统评测数据 链接: http://pan.baid

算法-蓝桥杯习题(六)

蓝桥杯习题 蓝桥杯练习系统习题加答案,总共分为6部分,90%习题使用C语言解答,部分使用C++或者Java.大部分习题为搜索参考或者别人提供所得,不足之处在所难免,恳请批评指正(预计200多题,习题仅供学习交流) 目录 算法训练(详见 算法-蓝桥杯习题(一))Go 算法训练(详见 算法-蓝桥杯习题(二))Go 算法提高(waiting...) 历届试题(详见 算法-蓝桥杯习题(六))Go 历届试题(详见 算法-蓝桥杯习题(七))Go 蓝桥杯练习系统评测数据 链接: http://pan.baid

蓝桥杯练习系统题解

转于:http://www.cnblogs.com/cshhr/p/3550014.html 蓝桥杯官网练习系统题解(非VIP) BEGIN-4(Fibonacci数列) 有递推公式,大家都知道用递推公式求,仅仅要记得在递推的时候同一时候取模求好 这里给一份另类代码,用矩阵高速幂求,事实上还有循环节 /* (1 1) * (Fn-1) = ( Fn )//矩阵相乘,将就着看吧 (1 0) (Fn-2) (Fn-1) (1 1) * (1 1) * (Fn-2) = ( Fn ) (1 0) (1