【1错笔记】城市的税金——排序解决大范围次数统计问题

本文通过分析一道关于城市税金的问题,探讨如何利用排序技巧高效解决大范围内次数统计的难题。文章详述了题目背景、输入输出描述,以及在处理数据写入和读出时需要注意的细节,特别是对于大整数范围的统计,通过排序避免了遍历整个范围导致的超时问题。作者强调了排序在解决问题中的重要性,并分享了AC代码,旨在帮助读者理解和掌握这类问题的解决策略。
摘要由CSDN通过智能技术生成

城市的税金——排序解决大范围次数统计问题

链接:https://ac.nowcoder.com/acm/contest/3036/D
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

影从者,并非真正的从者,而是一种’量产’从者,或是一种劣化从者。
而虚假的圣杯,准确说是残缺的圣杯,理所当然的只能召唤出影从者这种非正常使魔。但这也能称之为奇迹了,并不是凭依任何实体,而是自己创造出实体的魔术仪式。那家伙,也能称之为天才了吧。
虽然他想要完全掌控这虚假的圣杯,但是总有缺憾。
面对眼前这个从者(servant),我不知道该怎么办。他浑身上下都被不祥的黑雾包围着,连面貌都无法看清,很难说他到底还是不是保持清醒的状态。
「虽然能明显感觉到,你不是御主(master),但曾是吧」
「居然还保持着理智吗」我有些惊讶
「是啊,我才刚刚被圣杯召唤而来,但显然这圣杯很不对劲是吧」虽然无法看清他的表情,但我感觉到他是在苦笑「所以我也需要一个御主进行魔力供给」
「你是想让我和你签订契约么」
「不错,我相信你也是需要我的力量的吧」他似乎笑了「但是我也不能就这样简单的签订,如果你能回答我的问题,那么我就认可你吧」
「洗耳恭听」
「我曾是一名国王,也是一名十字军骑士。我征战过无数沙场,也攻克过无数的堡垒。这N座被我所征服的城市,要定期向我上贡一定的金额,但是计算税金的公式异常复杂和繁琐。而且随时都会有概率进行税金的修改。我会告诉你他们一开始所需要缴纳的税金,而且也会告诉你什么时候会对编号从L到R的城市进行税金修改,但当我向你提问的时候,你要回答我编号从L到R的城市当中,相同税金金额出现次数最多的出现次数」
「轻而易举,狮心王,理查一世」

输入描述:

第一行输入两个整数N,M (1<=N, M<=100),其中N表示理查一世所征服的城市个数,M表示理查一世对城市税金的修改次数和对税金的询问次数之和。第二行输入N个整数pi (0<=pi<=109),表示N个城市最初所需缴纳的税金金额。
接下来M行,每行输入为以下两种中的其中一种:
1 L R, (1 <= L<=R <= N)表示对编号从L到R的城市进行税金修改, 其中修改公式为:p1=p0*251%996*404*123,(p0和p1分别代表修改前的税金和修改后的税金)。
2 L R, (1 <= L<=R <= N)表示此时理查一世需要知道编号从L到R的城市中,相同税金金额出现次数最多的金额的出现次数。  

输出描述:

对于输入格式为’2 L R’的询问单独输出一行进行回答

示例1

输入

😉

6 5
1 2 3 4 5 3
1 1 6
2 1 6
1 3 5
1 2 4
2 2 4

输出

😉

2
1

说明

注意运算过程中所有数不超过long long的范围。
第一次操作后,6个数分别为12472692 24945384 37418076 397536 12870228 37418076。
第二次操作后,输出2(出现次数最多的是37418076)。
第三次操作后,6个数分别为12472692 24945384 34585632 13118688 41144976 37418076。
第四次操作后,6个数分别为12472692 6559344 2981520 36970848 41144976 37418076。
第五次操作后,输出1

问题分析:

其实这道题真的没什么思考的难度,考察的全是基本功,但是自己实力真的好弱,总是死在一些小问题上面,代码的质量也不算很高。

哎,先批判自己一下,下面详细讲解下这道题

这道题在输入数据后进行的操作无非就两类,一类是写入,一类是读出。

对于写入

我犯了一个很大的基本功问题,也是我自己排查了很久找不到问题的痛苦点

city[i] = city[i]*251%996*404*123
≠
city[i] *= 251%996*404*123

大佬看到这估计不禁吐槽,这都能错?也许也有些朋友和我一样,为什么不等价???

关键就出问题在%的运算符上,我又写了一段测试代码上机实验下给大家看下原因所在

#include <bits/stdc++.h>
using namespace std;

int main()
{
	long long int b=251 % 996 * 404 * 123;
	cout << "b=" << b << endl;
	
	long long int a=5;
	
	a *= 251 % 996 * 404 * 123;
	cout << "a=" << a << endl;
	
	a=5;
	a = a * 251 % 996 * 404 * 123;
	
	cout << "a=" << a << endl;
}

输出结果如下

b=12472692
a=62363460
a=12870228

对于读出

统计次数这件事情之前写题目又遇到过,比如这道题目,当时我学到的解决方案是下标嵌套,但这种方法只能解决范围小的次数统计,比如这道题的26个字母。可是我们看看这道题,最大可能到long long int,也就是21亿啊!!况且每个城市的税金是散布随机在1~21亿的,要是每一次都从1循环到21亿找出最大次数,必超时呀!试都不用试(遍历21亿遍说不定我的电脑会直接卡死hhh)。

那么我们要如何解决大范围次数统计问题呢?

当当当~有人曾经说过

遇事不决就排序

嗯,之前我就说过排序的重要性

回旋星空——妙用排序

强迫症的序列——思维转换 细节问题

珠心算测验——数组去重

那在这道题目,我们可不可以把city的数据拷贝出来后排序一下(这样子税金相同的城市就会挨在一起啦)那我们再遍历统计一下会不会更快呢?


AC代码:

#include <bits/stdc++.h>
using namespace std;

//记得用lli别溢出了
long long int city[101];
long long int num[101];

int main()
{
	int n,m;
	cin >> n >> m;
	
	//输入数据
	int i;
	int command;
	int flagl,flagr;
	for ( i=1; i<=n; i++ )
		cin >> city[i];

	while ( m-- )
	{
		cin >> command >> flagl >> flagr;
		if ( command == 1 )
			for ( i=flagl; i<=flagr; i++ )
			//注意别用*=啦
				city[i] = city[i]*251%996*404*123;
		else
		{
		//拷贝数组 不要影响原来的数组
			int k=1;
			for ( i=flagl; i<=flagr; i++ )
				num[k++] = city[i];
			k--;
			//注意要是num+1,因为从i开始记录数据的
			sort ( num+1, num+1+k );
			
			int ans=0,sum=1;
			for ( i=2; i<=k; i++ )
				if ( num[i] == num[i-1] )
					sum++;
				else
				{
					if ( sum>ans )
						ans = sum;
					//这个sum要拿到if外面,第一次交上去的时候
					//就是因为把它放到if导致只对了一半的数据点
					//太蠢了~!!!
					//其实之前我也经常出这种错误
					//希望给你也给我一个警示!
					sum = 1;
				}	
			
			//防止最后一个也是num[i] == num[i-1]而导致没有记录到ans里面
			if ( sum>ans )
				ans = sum;
			cout << ans << endl;		
		}
	}

}

写在后面:

为了确保大家能够看懂这篇文章,我尽量每字每句都详细讲解,给出证明和解释,真心希望你能够在阅读此篇文章后从中多多少少有所收获。因此每篇文章我都投入了大量的时间和精力,去举例,去说明,去分析,如果你觉得这篇文章写的还不错,点赞、关注和收藏一键三连就是对我最大的鼓励啦,我以后也会写更多更高质量的文章!也欢迎一起讨论指出文章可能存在的逻辑问题~

开通了微信公众号 欢迎关注~精选CSDN的文章发布 更优质的排版 更丰富的学习资源分享
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值