题意:
给出n个数,这个数一段区间和这样定义 sum[i,j]= ai - ai+1 +......+(-1)^(j-i)aj.给出一个数k,问是否存在一个sum[i,j]==k
题解:
我们手下得出前缀和,然后从后往前推,判断sum[i-1]-k或sum[i-1]+k是否在hash中,然后将sum[i]存入hash。因为题目求的是 sum[j]-sum[i]==k,那么我们将式子变形 sum[i]+k == sum[j] 这样只要判断前者是否在hash中出现就计算了出了i到之后所有j的情况。这题非常坑,读入超时,要手写读入。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<hash_map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef __int64 ll;
const int oo=0x3f3f3f3f;
const ll OO=1LL<<61;
const int MOD=10007;
const int maxn=1000005;
ll sum[maxn];
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;
}
}mat;
template <class T>
inline bool read(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;
}
int main(){
int n,k,T,sig,f;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
mat.init();
sig=1;f=0;
read(n);
read(k);
sum[0]=0;
for(int i=1;i<=n;i++){
read(sum[i]);
sum[i]=sum[i-1]+sig*sum[i];
sig*=-1;
}
mat.insert(sum[n]);
for(int i=n;i>=1&&f==0;i--){
if(i&1){
if(mat.check(sum[i-1]+k))f=1;
}else{
if(mat.check(sum[i-1]-k))f=1;
}
mat.insert(sum[i-1]);
}
if(f)printf("Case #%d: Yes.\n",cas);
else printf("Case #%d: No.\n",cas);
}
return 0;
}