中途相遇法,哈希技术(和为0的4个值,uva 1152)

来源:互联网 发布:教师网络培训总结 编辑:程序博客网 时间:2024/06/05 05:28

题目具有对称性,则可以同时从两边出发来找答案,因为时间复杂度由最大的决定,因此让两边时间复杂度尽量一样可以降低总体的时间复杂度,此题中n^2logn+n^2logn<n^4+1。虽然平摊时间复杂度后就得多考虑一个检索的时间复杂度,然而还是更快。双向广度优先搜索就有点像,虽然双向的时间复杂度都相同,但是平摊了数据之后,n^2+n^2<(2n)^2+1。


试了下map,9秒超时,用哈希3.540秒。还是快很多的。

因为map随着数据量的增多,logn的时间复杂度开始拖慢速度。

而哈希大部分时候都是O(1),极端情况下是O(n)。

极端情况一般都不用考虑,除非题目是特殊设计专门来狙击hash的,但这几乎不可能,谁那么蛋疼。

普遍的情况下hash还是远快的。

hashsize开大一点,也会快很多。

以空间换时间嘛。

hash技术本来就是在空间与时间中寻找一个平衡点的。


紫书上讲的哈希是开了一个很大的next数组的,事实上很多时候都开不下吧。

只能new节点或者用vector了。

vector更好用。


#include<bits/stdc++.h>#define hashsize 1000000using namespace std;int main(){    int t;    scanf("%d",&t);    while(t--)    {        vector<int>Hash[hashsize];        int n;        scanf("%d",&n);        vector<int>vec[4];        while(n--)        {            int temp;            for(int i=0;i<4;i++)            {                scanf("%d",&temp);                vec[i].push_back(temp);            }        }        for(unsigned int i=0;i<vec[0].size();i++)            for(unsigned int j=0;j<vec[1].size();j++)            {                int s=vec[0][i]+vec[1][j];                int h=abs(s)%hashsize;                Hash[h].push_back(s);            }        int ans=0;        for(unsigned int i=0;i<vec[2].size();i++)            for(unsigned int j=0;j<vec[3].size();j++)            {                int s=-vec[2][i]-vec[3][j];                int h=abs(s)%hashsize;                int cnt=0;                for(unsigned int k=0;k<Hash[h].size();k++)                    if(Hash[h][k]==s)                        cnt++;                ans+=cnt;            }        printf("%d\n",ans);        if(t) puts("");    }    return 0;}


0 0