[问题] 数列问题

楼主: williamd4112 (Williamd)   2015-01-31 17:44:40
原始题目:(非作业)
http://acm.cs.nthu.edu.tw/problem.php?hash=9c16f6606460d1543759fc966b9bb797#
简单叙述一下题目:
给一串有n个数字的数列
以及q个[a,b]的区间
如果第i个区间之后有两个点数总和小于第i个区间的区间,则得到A+的人加1
我的作法
求区间总和:
(1)建立一个n*n的方阵来存
summap[1][2]: 从1 ~ 2的总和
summap[3][6]: 从3 ~ 6的总和
在读取序列时一起进行, 所以花了(n)* (n+1) / 2的时间来进行
(2)读到区间后线性加总
譬如读取到2 6的区间, 就把数列中从[1] ~ [5]的元素加总
最差状况每个区间都是[1, n]的话,需要进行n * q次
储存:
(1)list:
宣告一个struct 来纪录
sum(区间的和),
counter(判断其后是否有两个小于自己的sum的数量)
先把数列完整读入后,建立一个list来存以上的结构
每读入一组区间, 建立一个结构来存,
然后判断读入的这个结构对list中的元素的counter的贡献
(如果conuter == 2则ans++, 之后把该元素从list中erase)
(2)阵列:
建立两个大小为n的阵列,分别存sum, counter
每读取一个区间就扫一次sum阵列
如果sum[i] > sum_current_input则counter++
如果counter == 2时, ans加1次(不会重复加, 因为只有counter < 2时才会递增counter
结果:
summap目前会RE , 还在找问题, 可是summap效能分析起来比线性求和还要差...
所以考虑往别的方向找答案
线性求和的方式搭配list, array都是TLE...
还有哪里可以改进效能的吗?
求和的地方实在想不到其他优化的方法了...
有没有办法减少读取一个区间后, 判断对数列影响的时间呢?
或是有其他方法?
作者: guest2 (wayne)   2015-01-31 20:51:00
你效能分析的结论怪怪的,Q跟N范围一样两个方法都是O(N^2)吧hint: sum(A...B)=sum(1...B)-sum(1...A-1)
楼主: williamd4112 (Williamd)   2015-01-31 22:24:00
阿...看到hint突然好想撞墙...根本就不用方阵来存阿只要花O(n)时间跑一次prefix sum就好.............
作者: guest2 (wayne)   2015-01-31 23:11:00
另外假设你得到每个人的分数score[1...Q]从反方向处理会比你从正向用count数更快complexity会从O(QK)=>O(Q)抱歉 应该是从O(Q^2)=>O(Q)
楼主: williamd4112 (Williamd)   2015-02-01 00:05:00
从反向可以做到O(Q)?!如果可希望能提示更多...
作者: aaaaajack (丁丁是个人才)   2015-02-01 02:29:00
先排序一遍找每个人的排位然后用fenwick tree倒著作回来应该可以做到O(QlogQ)又或者简单一点用priority_queue维护最小k个数怎么做到O(Q)我就比较没概念了,一时之间没想法
作者: guest2 (wayne)   2015-02-01 12:21:00
关键在于比后面k个人大第Q-K到第Q个人一定不及格第Q-K-1要及格要大于后面K个从Q-K-1到1每个人都要大于后面第K小的思考如何在新增一个元素进array的同时在O(1)时间找到第K小当然你必须先花O(K)的时间找到你要的资讯抱歉 aaaaa大是对的,应该是O(QlogQ)用priority_queue维护最小k个数才对
楼主: williamd4112 (Williamd)   2015-02-01 14:52:00
http://pastebin.com/mJmwVgeD 昨天也是想到用pq来但当时没有想到说维护k个数字就好xd但这段code还是re了...看来还得花一段时间来debug..
作者: guest2 (wayne)   2015-02-01 15:21:00
array大小可以动态改变??!
楼主: williamd4112 (Williamd)   2015-02-01 16:34:00
上面这段是因为用priority_queue跑RE...想说换个类换成heap来做不知道会不会正确,结果还是re...看了好久没看出哪里可能RE说...AC了,原来内存很吃紧,不能用long long而seq[n]也是多开的空间,然后sums[n]应该改成sums[q不过看Rank有人可以做到0.001 ...我目前只能做到0.444...
作者: guest2 (wayne)   2015-02-01 18:59:00
原来 int seq[n]; 这种写法合法啊...我还以为compiler会Er要解内存大小RE的问题可以把变量丢到global变量啦用long long并没有错,可能的范围-100000000~100000000本来就应该宣告成long long
楼主: williamd4112 (Williamd)   2015-02-01 21:38:00
seq[n]那个写法我记得以前上课时也是被告诫过...不过后来compiler都会过就没再去想了,我查看看
作者: FRAXIS (喔喔)   2015-02-01 22:22:00
int seq[n]是C99的功能 找wiki的Variable-length array
作者: suhorng ( )   2015-02-02 01:28:00
C++ 的话就完全是 compiler extension 了
作者: lmr3796 (Toro)   2015-02-21 00:23:00
C99的VLA跟终于可以for(int i;;)是我放下ansi c的关键XD

Links booklink

Contact Us: admin [ a t ] ucptt.com