现在的位置: 首页 > 综合 > 正文

hdu 5183 Negative and Positive (NP)

2019年02月20日 ⁄ 综合 ⁄ 共 1103字 ⁄ 字号 评论关闭

题意:首先给出n个数,和K,然后问有没有一个二元组满足K= SUM(I, J), SUM(I, J) =
aiai+1+ai+2++(1)jiaj

首先我们假设存在这样的二元组(i,j)那么该二元组的(i,j)表示的就是一段连续的区间,即区间SUM(i ~ j )= K。那么在这个区间前面的区间就是(1~i-1),设SUM(1~i-1) = x,而这两段区间和就是SUM(1~j) = K + x = y。而SUM(a~b)可以通过处理前缀和得到,即,我们可以得到x和y,这样的话确定K有没有出现过,我们只需判断x(即y-K)在之前的区间里面存不存在即可。而 nlogn的时间只能有一种姿势过,即for的时候set(判断存在过与否)只能进行一次insert和find,两次就会T了

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

inline void read(ll &x){int flag = 0;x = 0;char c = getchar();if(c == '-') flag = 1;while(c < '0' || c > '9') {if(c == '-') flag = 1;c = getchar();}while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();if(flag) x = -x;}

set <ll> s;
LL a[1000005];
int main()
{
    int t, ca = 1;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        ll k;
        scanf("%d %I64d", &n, &k);
        for(int i = 1; i <= n; i++)
        {
            read(a[i]);
            if(i % 2 == 0)
                a[i] = -a[i];
        }
        s.clear();
        printf("Case #%d: ", ca++);
        for(int i = 1; i <= n; i++)
            a[i] += a[i-1];
        bool flag = 1;
        for(int i = n; i >= 0 && flag; i--)
        {
            if(i % 2 == 0)
            {
                if(s.find(a[i] + k) != s.end())
                    flag = 0;
            }
            else
            {
                if(s.find(a[i] - k) != s.end())
                    flag=0;
            }
            s.insert(a[i]);
        }
        if(flag)
            puts("No.");
        else
            puts("Yes.");
    }
    return 0;
}

抱歉!评论已关闭.