HDU 5183 Negative and Positive (NP) --Hashmap

题意:问有没有数对(i,j)(0<=i<=j<n),使得a[i]-a[i+1]+...+(-1)^(j-i)a[j]为K.

解法:两种方法,枚举起点或者枚举终点。

先保存前缀和:a1-a2+a3....+/- an

枚举起点法: 设起点为x,实际是枚举x-1,分两种情况:

1.起点x为奇,那么就看有没有a[j]-a[x-1] = K的,即a[j] = a[x-1]+K。因为奇数位置的ai数符为正。

2.起点x为偶,那么就看有没有a[j]-(-K) = a[x-1],即a[j] = a[x-1]-K。因为偶数位置ai数符为负,即x到j这一段的数是负的 选x为起点的x到j的这一段和,所以中间实际上是-K。

每次将sum[i]标记为出现过。

只需要一个hashmap即可。

由于枚举到一个起点x,需要判断a[j](j>x)是否出现,所以要逆序枚举。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
#define lll __int64
#define ll long long
using namespace std;
#define N 1000007

lll sum[N];
const unsigned long long SMod=1000007;
struct hashmap{
    struct Edge
    {
        long long num;
        int next;
    };
    Edge edge[2*N];
    int countedge;
    int head[SMod+100];

    void init()
    {
        memset(head,-1,sizeof(head));
        countedge=0;
    }

    void addedge(long long num)
    {
        int start=num%SMod;
        edge[countedge].next=head[start];
        edge[countedge].num=num;
        head[start]=countedge;
        countedge++;
    }

    int Find(long long num)
    {
        int start=num%SMod;
        int ind;
        for(ind=head[start]; ind!=-1; ind=edge[ind].next)
        {
            if(edge[ind].num==num)break;
        }
        return ind;
    }
}ST;

int main()
{
    int n,i,j,cs = 1,t,x,K;
    scanf("%d",&t);
    while(t--)
    {
        ST.init();
        scanf("%d%d",&n,&K);
        sum[0] = 0;
        for(i=1;i<=n;i++) {
            scanf("%d",&x);
            if(i%2) sum[i] = sum[i-1] + x;
            else    sum[i] = sum[i-1] - x;
        }
        ST.addedge(sum[n]);
        int tag = 0;
        for(i=n-1;i>=0;i--) {
            if(i%2 == 0 && ST.Find(sum[i]+K) != -1) { tag = 1; break; }
            if(i%2 && ST.Find(sum[i]-K) != -1) { tag = 1; break; }
            ST.addedge(sum[i]);
        }
        printf("Case #%d: ",cs++);
        if(tag) puts("Yes.");
        else    puts("No.");
    }
    return 0;
}

枚举终点法

建立两个hashmap,一个记录sum[1],sum[3],...sum[2*cnt+1] (2*cnt+1<=n)即奇数位置是否出现过,另一个记录偶数位置的sum值是否出现过。

枚举终点y的话,起点可能是1~y的任何一个(这里下标从题目中的0~n-1转为了1~n),当起点x=1的时候,这时NP-SUM(x,y) = sum[y], 记为XX。以n=4为例。

那么起点为2的时候整个值就等于 -XX+a1, (-(a1-a2+a3-a4) +a1 = a2-a3+a4))

起点为3的时候整个值等于 XX-sum[2]      (a1-a2+a3-a4 - (a1-a2) = a3-a4 )

...以此类推,归为两类 :

1. XX-sum[0] , XX-sum[2] , ... XX-sum[偶数] 是否为K

2. -XX+sum[1], -XX+sum[3], ... -XX+sum[奇数] 是否为K

设他们为K,那么即判断 XX-K在偶数的hashmap中有没有出现, 判断XX+K在奇数的hashmap中有没有出现。

每次将sum[i]加入到对应的hashmap中。

顺序枚举。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
#define lll __int64
#define ll long long
using namespace std;
#define N 1000007

const unsigned long long SMod=1000007;
struct hashmap{
    struct Edge
    {
        long long num;
        int next;
    };
    Edge edge[2*N];
    int countedge;
    int head[SMod+100];

    void init()
    {
        memset(head,-1,sizeof(head));
        countedge=0;
    }

    void addedge(long long num)
    {
        int start=num%SMod;
        edge[countedge].next=head[start];
        edge[countedge].num=num;
        head[start]=countedge;
        countedge++;
    }

    int Find(long long num)
    {
        int start=num%SMod;
        int ind;
        for(ind=head[start]; ind!=-1; ind=edge[ind].next)
        {
            if(edge[ind].num==num)break;
        }
        return ind;
    }
}mpe,mpo;

int main()
{
    int n,i,j,cs = 1,t,x,K;
    scanf("%d",&t);
    for(cs=1;cs<=t;cs++)
    {
        mpo.init();
        mpe.init();
        scanf("%d%d",&n,&K);
        lll sum = 0;
        mpe.addedge(0);
        int tag = 0;
        for(i=1;i<=n;i++) {
            scanf("%d",&x);
            if(i&1) sum += x;
            else    sum -= x;
            if(i&1) mpo.addedge(sum);
            else    mpe.addedge(sum);
            if(mpe.Find(sum-K) != -1) { tag = 1; }
            if(mpo.Find(sum+K) != -1) { tag = 1; }
        }
        printf("Case #%d: ",cs);
        if(tag) puts("Yes.");
        else    puts("No.");
    }
    return 0;
}

注意:

如果hashmap中的SMod 用宏定义的方式就会T, 用const unsigned long long 就不会。不知道为什么。

hashmap模板借鉴了love_dn的代码。

时间: 2024-08-27 09:41:20

HDU 5183 Negative and Positive (NP) --Hashmap的相关文章

HDU 5183 Negative and Positive (NP) (set + 读入外挂 乱搞)

Negative and Positive (NP) Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 502    Accepted Submission(s): 141 Problem Description When given an array (a0,a1,a2,?an?1) and an integer K, you are

HDU 5183 Negative and Positive (NP) (手写哈希)

题目链接:HDU 5183 Problem Description When given an array \((a_0,a_1,a_2,?a_{n?1})\) and an integer \(K\), you are expected to judge whether there is a pair \((i,j)(0≤i≤j<n)\) which makes that \(NP?sum(i,j)\) equals to \(K\) true. Here \(NP?sum(i,j)=a_i?

HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)

根据奇偶开两个hash表来记录后缀和.注意set会被卡,要手写hash表. 具体见代码: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 1000000 + 10; 6 const int HASH = 1000000 + 7; 7 typedef long long ll; 8 struct hashmap

hdu 5183 Negative and Positive (NP)(STL-集合【HASH】)

题意: When given an array (a0,a1,a2,?an−1) and an integer K, you are expected to judge whether there is a pair (i,j)(0≤i≤j<n) which makes that NP−sum(i,j) equals to K true. Here NP−sum(i,j)=ai−ai+1+ai+2+?+(−1)j−iaj 1≤n≤1000000,−1000000000≤ai≤1000000000

hdu 5183. Negative and Positive (哈希表)

Negative and Positive (NP) Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2177    Accepted Submission(s): 556 Problem Description When given an array (a0,a1,a2,?an−1) and an integer K, you are

[HDOJ 5183] Negative and Positive (NP) 【Hash】

题目链接:HDOJ - 5183 题目分析 分两种情况,奇数位正偶数位负或者相反. 从1到n枚举,在Hash表中查询 Sum[i] - k ,然后将 Sum[i] 加入 Hash 表中. BestCoder比赛的时候我写了 STL map, 然后TLE... 注意: Hash负数的时候 % 了一个质数,得到的是负数还要 + Mod !! 代码 #include <iostream> #include <cstdio> #include <cstdlib> #includ

Negative and Positive (NP) ( Hash 维护 )

Negative and Positive (NP) Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2846 Accepted Submission(s): 782 Problem Description When given an array (a0,a1,a2,?an?1) and an integer K, you are expec

hdu5183---Negative and Positive (NP)(HASHMAP)

Problem Description When given an array (a0,a1,a2,?an?1) and an integer K, you are expected to judge whether there is a pair (i,j)(0≤i≤j /************************************************************************* > File Name: hdu5183.cpp > Author: AL

hdu 5183(hash)

传送门:Negative and Positive (NP) 题意:给定一个数组(a0,a1,a2,?an−1)和一个整数K, 请来判断一下是否存在二元组(i,j)(0≤i≤j<n)使得 NP−sum(i,j) 刚好为K.这里NP−sum(i,j)=ai−ai+1+ai+2+?+(−1)j−iaj. 分析:根据a[i]的i为奇偶进行hash,维护两种前缀和 1)i为奇数开头:sum=a[i]-a[i+1]+a[i+2]... 2)i为偶数开头:sum=a[i]-a[i+1]+a[i+2]...