hdu5183 hash大法
维护前缀和sum[i]=a[0]-a[1]+a[2]-a[3]+…+(-1)^i*a[i]
枚举结尾i,然后在hash表中查询是否存在sum[i]-K的值。
如果当前i为奇数,则将sum[i]插入到hash表中。
上面考虑的是从i为偶数为开头的情况。
然后再考虑以奇数开头的情况,按照上述方法再做一次即可。
不同的是这次要维护的前缀和是sum[i]=-(a[0]-a[1]+a[2]-a[3]+…+(-1)^i*a[i])
I为偶数的时候将sum[i]插入到hash表。
总复杂度o(n)
注意一个tips:scanf读long long的时候别忘了%I64d,否则会出错
------注意几个黑科技orz-------
1.这题丧心病狂到了卡常数的程度= =,所以hash的时候用map肯定是不行的。。。。
借助了kuangbin原创的hash模板orz
const int HASH = 1000007; struct HASHMAP { int head[HASH],next[MAXN],size; long long state[MAXN]; void init() { size = 0; memset(head,-1,sizeof(head)); } bool check(long long val){ int h = (val%HASH+HASH)%HASH; for(int i = head[h];i != -1;i = next[i]) if(val == state[i]) return true; return false; } int insert(long long val) { int h = (val%HASH+HASH)%HASH; for(int i = head[h]; i != -1;i = next[i]) if(val == state[i]) { return 1; } state[size] = val; next[size] = head[h]; head[h] = size++; return 0; } } H1,H2;
init:初始化 insert:插入 check:查找是否存在
2.Huge Data,还需要读入优化:
基本思想就是把输入数据以一个一个字符的形式读入
template <class T> inline bool scan_d(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; //EOF while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; }
使用方法:scan_d(a[i]);
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define MAXN 1000010 5 #define LL long long 6 int a[MAXN]; 7 LL S1,S2; 8 LL k; 9 int n,TC; 10 11 const int HASH = 1000007; 12 struct HASHMAP 13 { 14 int head[HASH],next[MAXN],size; 15 long long state[MAXN]; 16 void init() 17 { 18 size = 0; 19 memset(head,-1,sizeof(head)); 20 } 21 bool check(long long val){ 22 int h = (val%HASH+HASH)%HASH; 23 for(int i = head[h];i != -1;i = next[i]) 24 if(val == state[i]) 25 return true; 26 return false; 27 } 28 int insert(long long val) 29 { 30 int h = (val%HASH+HASH)%HASH; 31 for(int i = head[h]; i != -1;i = next[i]) 32 if(val == state[i]) 33 { 34 return 1; 35 } 36 state[size] = val; 37 next[size] = head[h]; 38 head[h] = size++; 39 return 0; 40 } 41 } H1,H2; 42 43 44 template <class T> 45 inline bool scan_d(T &ret) { 46 char c; int sgn; 47 if(c=getchar(),c==EOF) return 0; //EOF 48 while(c!='-'&&(c<'0'||c>'9')) c=getchar(); 49 sgn=(c=='-')?-1:1; 50 ret=(c=='-')?0:(c-'0'); 51 while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); 52 ret*=sgn; 53 return 1; 54 } 55 56 57 int main() 58 { 59 //freopen("in.txt","r",stdin); 60 scanf("%d",&TC); 61 for (int TT=1;TT<=TC;TT++) 62 { 63 scanf("%d%I64d",&n,&k); 64 for (int i=0;i<n;i++) 65 scan_d(a[i]); 66 //scanf("%d",&a[i]); 67 68 bool ans=false; 69 H1.init(); 70 H2.init(); 71 H1.insert(0); 72 //H2.insert(0); 73 S1=a[0]; S2=-a[0]; 74 if (H1.check(S1-k)) ans=true; 75 if (H2.check(S2-k)) ans=true; 76 H2.insert(S2); 77 78 for (int i=1;i<n;i++) 79 { 80 if (i%2==0) 81 { 82 S1=S1+a[i]; 83 S2=S2-a[i]; 84 H2.insert(S2); 85 } 86 else 87 { 88 S2=S2+a[i]; 89 S1=S1-a[i]; 90 H1.insert(S1); 91 } 92 if (H1.check(S1-k)) 93 ans=true; 94 if (H2.check(S2-k)) 95 ans=true; 96 if (ans) break; 97 } 98 99 printf("Case #%d: ",TT); 100 if (ans) printf("Yes.\n"); else printf("No.\n"); 101 } 102 return 0; 103 }
HASH大法有时候真的蛮重要的orz
posted on 2015-03-08 18:27 Pentium.Labs 阅读(211) 评论(0) 编辑 收藏 举报