- 大部分OJ的内存都采取严格管理,比如定义
a[10]
,则内存方面只剩请10个,若越界访问,代码直接崩溃。 但Helloworld就不一样,只要访问越界次数不多,不严重,连RE也不会判。例如用c语言风格输入:
其他OJ上,如输入字符串长度为114514,则崩溃RE(有时侥幸会WA),这是因为scanf会自动在字符串末尾加入'\0'作为结束符以保证其他操作如strlen就不会出问题。 但是,当长度为114514时,scanf会在str[114514]位置放置'\0',然后RE。 有时候侥幸过了,但printf也是基于'\0'的,所以在没存上'\0'时,它会报你100%WA。 可Helloworld就不太一样,他只看代码的反应,而且和本地运行相似,有时候应该判RE时不判,WA也不对。char str[114514]; ... scanf("%s",str); ...
奇·论
#1990题解
这道题目与#288.[2004]合并果子
比较类似,想必思路应该是
for i in [1,n-1) then
sort a+i to a+n
q1 <- a[i]
q2 <- a[i+1]
a[i+1] <- ( q1 + q2 ) /k
其中,n为题目中的n,a为数组,k为题目中的k,q1和q2为两个int类型的临时变量,sort同sort(a+i,a+n,cmp)
(其中cmp将其转换为递减排序)。
很明显,如果一直这样一直sort,复杂度可想而知啊:O(n * n log2 n)至O(n^3)……
但可以水过哦
这里介绍优先队列,即大根堆,不必知道它是如何运作的,每次取top()值时,就可以得到队列中最大的元素!
代码部分(片段)
#include <queue>
#include <vector>//想要用优先队列就要带的东西
-
int n,k,w,a1,a2;//n和k同题目中的n和k;w为临时变量,用于存储w_i;a1和a2存储待处理项,即要“合并”的两个数
priority_queue < int > q;//定义方法
//or
//priority_queue < int , vector < int > , less < int > > q;
就像queue一样,其中的int可以换成其它类,如string,char,double等。
其中的lass参数决定了排序方案,greater决定每次取top()值为队列中最小的值(pop()同理),而lass可以让其返回最大的值。
用这个方案可以减少一定的复杂度:O(n * n log2 n),要更快的会就只能去追求桶排序了。
for(int i=1;i<=n;i++){
scanf("%d",&w);//我下过狠言:从此再也不用cin,cout。(前几天的一次60就是因此)
q.push(w);//与queue同理
}
-
while(q.size()>1){//每次处理两个,所以必须大于一
a1=q.top(),q.pop();
a2=q.top(),q.pop();//取出来
q.push((a1+a2)/k);//模拟
}
看起来还是很简单的,但这样做法有个弊端:由于每次都取两个数,而结果强制去小数,所以合并了[2,2]->(2+2)/2=2和[2,3]->(2+3)/2=2可以说是等价的,但是会浪费一个数2,所以有HACK数据:
4 5
30 31 33 34
其实Luogu上很多人过不去正是因此。应为我们的算法很天真:
30 31 33 34
merge [34,33]
13 30 31
merge [31,30]
12 13
merge [13,12]
5
但实际上……
merge [30,34]
12 31 33
merge [31,33]
12 12
merge [12,12]
4
所以这道题目在Luogu上很有争议的,而如果想试试,可以看看这个:https://www.luogu.com.cn/discuss/464526?page=5 ,可以看出,这有点不实际,所以暂时用这个方法是没有问题的,有待更多研究和结论。
幻灯片
F.字符串配对题解
先看题。
http://go.helloworldroom.com:50080/problem/2529
由题目可知,这道题要用排序。
答案ans初始化可以为1,计数方式为乘法原理:
在找到相同数时,并不是ans=ans或者ans=j这种东西,应该ans*=相同数的数量。
数组要开大一些。
排序建议用sort。
坑:
1.要用bool变量保存结果是否更改过。
2.如果字符串长度为1,那么"1."这部分代码甚至执行不到,因此要事先判断。