HDU 5183 Negative and Positive (NP)(哈希 hash)——BestCoder Round #32

来源:互联网 发布:c语言模拟自动饮料机 编辑:程序博客网 时间:2024/06/06 11:02

Negative and Positive (NP)

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


Problem Description
When given an array (a0,a1,a2,an1) and an integer K, you are expected to judge whether there is a pair (i,j)(0ij<n) which makes that NPsum(i,j) equals to K true. Here NPsum(i,j)=aiai+1+ai+2++(1)jiaj
 

Input
Multi test cases. In the first line of the input file there is an integer T indicates the number of test cases.
In the next 2T lines, it will list the data for each test case.
Each case occupies two lines, the first line contain two integers n and K which are mentioned above.
The second line contain (a0,a1,a2,an1)separated by exact one space.
[Technical Specification]
All input items are integers.
0<T25,1n1000000,1000000000ai1000000000,1000000000K1000000000
 

Output
For each case,the output should occupies exactly one line. The output format is Case #id: ans, here id is the data number starting from 1; ans is “Yes.” or “No.” (without quote) according to whether you can find (i,j) which makes PNsum(i,j) equals to K.
See the sample for more details.
 

Sample Input
21 112 1-1 0
 

Sample Output
Case #1: Yes.Case #2: No.
Hint
If input is huge, fast IO method is recommended.
 

Source
BestCoder Round #32
 

/************************************************************************/

附上该题对应的中文题

Negative and Positive (NP)

 
 Time Limit: 3000/1500 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
给定一个数组\left( {{a_0},{a_1},{a_2}, \cdots {a_{n - 1}}} \right)(a0,a1,a2,an1)和一个整数KK, 请来判断一下是否存在二元组(i,j) (0 \leq i \leq j< n)(i,j)(0ij<n)使得 NP-sum(i,j)NPsum(i,j) 刚好为KK。这里
输入描述
多组测试数据。在文件的第一行给出一个TT,表示有TT组数据。在接下来的2*T2T行里,将会给出每一组数据。每一组数据占两行,第一行包含nnKK。第二行包含\left( {{a_0},{a_1},{a_2}, \cdots {a_{n - 1}}} \right)(a0,a1,a2,an1)以一个空格分开。[参数说明]所有输入均为整数。0 < T \leq 25,1 \leq n \leq 1000000,-1000000000 \leq ai \leq 1000000000,-1000000000 \leq K \leq 10000000000<T25,1n1000000,1000000000ai1000000000,1000000000K1000000000
输出描述
对于每一个数据,输出占一行,输出格式是Case #id: ans,这儿id是数据编号,从1开始,ans是根据是否找到满足的二元组而定为“Yes.” 或 “No.” (不包含引号)看样例可以获得更多的信息。
输入样例
21 112 1-1 0
输出样例
Case #1: Yes.Case #2: No.
Hint
如果数据比较多,建议使用快速读入。
/****************************************************/

出题人的解题思路:

维护前缀和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)
该题题意很明确,就是问是否存在一个二元组(i,j),使得NP-sum(i,j)=k

该题的解法,出题人讲得很明确,利用哈希函数,我们将求得的sum[i](前i项的NP-sum值)求出来放入哈希表中,遍历一遍即可判断是否存在一个二元组满足条件

我要提的一点是题目的读入优化,因为题目的数据比较多,普通的输入耗的时间也会比较长,容易TLE,所以此题需用到读入优化,详情可点击链接

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#include<math.h>#include<vector>#include<map>#include<set>#include<stdlib.h>#include<cmath>#include<string>#include<algorithm>#include<iostream>#define exp 1e-10#define ll __int64using namespace std;const int N = 1000005;const int inf = 1000000000;const int mod = 1000005;struct node{    int to;    ll v;}e[N];int s[N],h[N],p;void add(ll x){    e[p].v=x;    x=abs(x)%N;    e[p].to=h[x];    h[x]=p++;}bool check(ll x){    int k=abs(x)%N;    for(int i=h[k];i+1;i=e[i].to)        if(e[i].v==x)            return true;    return false;}int get_val(int &ret){    int sgn=1;    char c;    while(((c=getchar())<'0'||c>'9')&&c!='-');    if(c=='-')        sgn=-1,ret=0;    else        ret=c-'0';    while((c=getchar())>='0'&&c<='9')        ret=ret*10+c-'0';    ret*=sgn;}int main(){    int t,n,k,i,j=1;    ll sum;    get_val(t);    while(t--)    {        sum=0;p=0;        memset(h,-1,sizeof(h));        get_val(n);        get_val(k);        for(i=0;i<n;i++)            get_val(s[n-i-1]);        add(0);        printf("Case #%d: ",j++);        for(i=0;i<n;i++)        {            sum+=(i&1)?-s[i]:s[i];            add(sum);            if(i&1)            {                if(check(sum+k))                {                    puts("Yes.");                    break;                }            }            else if(check(sum-k))            {                puts("Yes.");                break;            }        }        if(i>=n)            puts("No.");    }    return 0;}
菜鸟成长记


0 0
原创粉丝点击