hdu5183Negative and Positive (NP))——手写Hash&&模板

题意:问是否存在一段区间其加减交错和为K。

显然,我们可以用set保存前缀和,然后枚举一个端点查找。具体的

hdu5183Negative and Positive (NP))——手写Hash&&模板

若在st1中查找 $t$,为 $sum-t=-k$,在st2中则是 $sum-t=k$。

注意这样作差的话,没有考虑到 $a_1$ 开始的,只要在st2中插入一个0即可。

然而,这题卡set,必须手写hashmap(说实话,之前不太相信会有卡set的题!)

后来发现unordered_set也能过(刚好过)

hdu5183Negative and Positive (NP))——手写Hash&&模板

分别是unordered_set、set、手写hashmap

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 1000000 + 10;
int n, k;
//set<ll>st1, st2;

const unsigned long long SMod = 1000007;
struct Hashmap
{
    struct Node
    {
        long long num;
        int next;
    };
    Node nodes[2*maxn];
    int cnt_node;       //节点个数
    int head[SMod+10];  //链表的头

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

    void insert(long long num)
    {
        int pos = num % SMod;  //在链表头中的位置
        nodes[cnt_node].next = head[pos];
        nodes[cnt_node].num = num;
        head[pos] = cnt_node;
        cnt_node++;
    }

    long long find(long long num)  //找到的话返回节点编号,没找到返回-1
    {
        int pos = num % SMod;
        for(int i = head[pos]; i != -1; i = nodes[i].next)
        {
            if(nodes[i].num == num)  return i;
        }
        return -1;
    }
}st1, st2;

int main()
{
    int T, kase=0;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &k);
        ll sum = 0;
        bool flag = false;
        st1.init(); st2.init(); st2.insert(0);
        for(int i = 1;i <= n;i++)
        {
            int tmp;
            scanf("%d", &tmp);
            if(i&1){ sum += tmp; st1.insert(sum);}
            else { sum -= tmp; st2.insert(sum);}  //printf("sum:%d
", sum);
            if(st1.find(sum+k) != -1|| st2.find(sum-k) != -1)  flag = true;
        }

        printf("Case #%d: ", ++kase);
        if(flag)  printf("Yes.
");
        else  printf("No.
");
    }
}