题意: 给出k个数列,要求选出任意两个数列i和j,使得第i个数列减去第n个数的和,等于第j个数列减去第m个数的和。求i、j、nn、m。
题目链接:http://codeforces.com/contest/988/problem/C
错误想法
统计所有数列的和(a[i].value表示第i个数列的和是多少),枚举两个数列(i、j),枚举第i个数列的每个数字n。那么我们就确定了四个所求数中的三个,对于第四个数m进行二分即可。 \[ a[i].value - n == a[j].value - m \] 1
2
3
4
5
6for( 数列 i = 1 to k )
for( 数列 j = 1 to i )
for( 元素 n = 1 to a[i].size() )
二分查找a[j]中是否存在m( m == a[j].value - a[i],value + n )
找到了输出YES.
输出NO
算法复杂度: \(O(k^3*logn)\)
一开始考虑到这个肯定过不了,不过无意间看到保证所有数据元素加起来不超过\(2e5\)个,不知道怎么脑子抽了就写了。 但是实际上显然不能过的,只要每个数列一个数字,直接将近\(4e10\),TLE是肯定的。 写了以后疯狂Wrong Answer.... TLE我也就接受了。应该是正常的,然而疯狂WA是怎么一回事。 查了两三天的错,主要的问题是: - 二分没有排序! (这问题,orz) - 排序后,某下标错了……
1 |
|

感觉自己问题出在,想到了一个简单的不行的结论,就以为get到了这道题的trick,然后就非常兴奋的撞了上去越陷越深。
正确做法
1 | map< 去掉一个数后的和 , |
只要遍历每一个数字,当这个数字在map中没有出现过的时候,放入这样一个map中,当这个数字在map中出现了的时候,输出map中记录的第一次出现的位置和当前位置即可。 时间复杂度:\(O(k*logn)\)
1 |
|
总结
以后对于这种出现两次,要找一对的情况之类的,可以考虑先存一下第一次出现的时候的情况,然后第二次出现的时候直接输出。