HDU 5183 Negative and Positive (NP) 前缀和+哈希

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5183

bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=570&pid=1002

题解:

前缀和+哈希

维护两张哈希表hash1,hash2,一张维护前缀和sum=a[0]-a[1]+a[2]-a[3]+...+(-1)^i*a[i],另一张维护-sum=-a[0]+a[1]-a[2]+a[3]-...+(-1)^(i+1)*a[i];当i为奇数的时候,插入到第一张哈希表hash1,当i为偶数的时候插入到第二张表hash2,每次查询在hash1中是否存在sum-k,或在hash2中是否存在-sum-k,如果有一个条件成立,则说明有解。否则继续做下去,直到最后还没有答案则无解。

代码:

hash表大小设为100007,输入为int,用vector做hash,g++,1185MS高飘

 1 #include<map>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 typedef long long LL;
10 
11 const int mod = 100007;
12 
13 int n,k;
14 
15 vector<LL> v[2][mod];
16 
17 int Hash(LL x) {
18     return (x%mod + mod) % mod;
19 }
20 
21 bool que(LL x,int type) {
22     int key = Hash(x);
23     for (int i = 0; i < v[type][key].size(); i++) {
24         if (v[type][key][i] == x) return true;
25     }
26     return false;
27 } 
28 
29 void add(LL x,int type) {
30     int key = Hash(x);
31     if (!que(x,type)) {
32         v[type][key].push_back(x);
33     }
34 }
35 
36 void init() {
37     for (int i = 0; i < mod; i++) {
38         v[0][i].clear();  
39         v[1][i].clear();
40     }
41 }
42 
43 int main() {
44     int tc, kase=0;
45     scanf("%d", &tc);
46     while (tc--) {
47         scanf("%d%d", &n, &k);
48         init();
49         LL sum = 0;
50         bool ans = 0;
51         for (int i = 0; i < n; i++) {
52             int x;
53             scanf("%d", &x);
54             if (i & 1) sum -= x;
55             else sum += x;
56             if (que(sum - k,0) || que(-sum - k,1)) {
57                 ans = true;
58             }
59             if (i & 1) add(sum, 0);
60             else add(-sum, 1);
61         }
62         if (sum == k) ans = true;
63         printf("Case #%d: ",++kase);
64         if (ans) printf("Yes.
");
65         else printf("No.
");
66     }
67     return 0;
68 }
View Code

hash表大小1000007,输入int,邻接表做hash,g++, 811ms

 1 #include<map>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 typedef long long LL;
10 
11 const int mod = 1000007;
12 const int maxn=1000000+10;
13 
14 struct Edge{
15     LL x; int ne;
16     Edge(LL x,int ne):x(x),ne(ne){}
17     Edge(){}
18 }egs[maxn*2];
19 
20 int n,k;
21 
22 int v[2][mod],tot;
23 
24 int Hash(LL x) {
25     return (x%mod + mod) % mod;
26 }
27 
28 bool que(LL x,int type) {
29     int key = Hash(x);
30     int p=v[type][key];
31     while(p!=-1){
32         Edge& e=egs[p];
33         if(e.x==x) return true;
34         p=e.ne;
35     }
36     return false;
37 } 
38 
39 void add(LL x,int type) {
40     int key = Hash(x);
41     if (!que(x,type)) {
42         egs[tot]=Edge(x,v[type][key]);
43         v[type][key]=tot++;
44     }
45 }
46 
47 void init() {
48     memset(v,-1,sizeof(v));
49     tot=0;
50 }
51 
52 int main() {
53     int tc, kase=0;
54     scanf("%d", &tc);
55     while (tc--) {
56         scanf("%d%d", &n, &k);
57         init();
58         LL sum = 0;
59         bool ans = 0;
60         for (int i = 0; i < n; i++) {
61             int x;
62             scanf("%d", &x);
63             if (i & 1) sum -= x;
64             else sum += x;
65             if (que(sum - k,0) || que(-sum - k,1)) {
66                 ans = true;
67             }
68             if (i & 1) add(sum, 0);
69             else add(-sum, 1);
70         }
71         if (sum == k) ans = true;
72         printf("Case #%d: ",++kase);
73         if (ans) printf("Yes.
");
74         else printf("No.
");
75     }
76     return 0;
77 }