直接扫一遍,用hash散布,然后查询,可以在o(n)下得到结果
用前缀和-k,然后查询前面的前缀和有没有==前缀和-k,有就能性
查询时插入的前缀和,必须是以负数结尾的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <vector>
#define MAX 1000007
using namespace std;
typedef long long LL;
int t,n;
LL sum[MAX],a,k;
vector<LL> v[MAX];
int Hash( LL num )
{
return (num%MAX+MAX)%MAX;
}
void add ( LL num )
{
int id = Hash ( num );
v[id].push_back ( num );
}
bool check ( LL num )
{
int id = Hash ( num );
int len = v[id].size ( );
for ( int i = 0 ; i < len ; i++ )
if ( v[id][i] == num ) return true;
return false;
}
void Clear ( )
{
for ( int i = 0 ; i < MAX ; i++ ) v[i].clear();
}
int main ( )
{
scanf ( "%d" , &t );
int c = 1;
while ( t-- )
{
scanf ( "%d%lld" , &n , &k );
sum[0] = 0;
for ( int i = 1 ; i <= n ; i++ )
{
scanf ( "%lld" , &a );
sum[i] = sum[i-1] + a*(i&1?1:-1);
}
Clear ( );
add ( 0 );
bool flag = false;
for ( int i = 1 ; i <= n ; i++ )
{
if ( check ( sum[i] - k ) )
{
flag = true;
break;
}
if ( !(i&1) )add ( sum[i] );
}
if ( !flag )
{
Clear ( );
for ( int i = 1 ; i <= n ; i++ )
sum[i] = - sum[i];
for ( int i = 1 ; i <= n ; i++ )
{
if ( check ( sum[i] - k ) )
{
flag = true;
break;
}
if ( i&1 )add ( sum[i] );
}
}
printf ( "Case #%d: " , c++ );
if ( flag ) puts ( "Yes." );
else puts ( "No." );
}
}