HDU 5172 GTY's gay friends(BestCoder Round #29)

Problem Description:
GTY has n gay friends. To manage them conveniently, every morning he ordered all his gay friends to stand in a line. Every gay friend has a characteristic value ai , to express how manly or how girlish he is. You, as GTY's assistant, have to answer GTY's queries. In each of GTY's queries, GTY will give you a range [l,r] . Because of GTY's strange hobbies, he wants there is a permutation [1..rl+1] in [l,r]. You need to let him know if there is such a permutation or not.
 
Input:
Multi test cases (about 3) . The first line contains two integers n and m ( 1n,m1000000 ), indicating the number of GTY's gay friends and the number of GTY's queries. the second line contains n numbers seperated by spaces. The ith number ai ( 1ain ) indicates GTY's ith gay friend's characteristic value. The next m lines describe GTY's queries. In each line there are two numbers l and r seperated by spaces ( 1lrn ), indicating the query range.
 
Output:
For each query, if there is a permutation [1..rl+1] in [l,r], print 'YES', else print 'NO'.
 
Sample Input:
8 5
2 1 3 4 5 2 3 1
1 3
1 1
2 2
4 8
1 5
3 2
1 1 1
1 1
1 2
 
Sample Output:
YES
NO
YES
YES
YES
YES
NO
题意:有一个长度为n的序列a,里面元素大小为1~n,有m次查询,每次查询位置区间[l,r]的对应元素是否含有{1,2,3……l-r+1}的每个元素。
分析:首先要必须保证[l,r]之间元素之和等于序列{1,2,3……l-r+1}的和,其次要保证[l,r]之间没有重复的元素,同时满足以上两个条件的区间才满足题意。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;

const int N=1e6+10;
const int INF=0x3f3f3f3f;
const int MOD=2008;

typedef long long LL;

struct node
{
    int left, right, Max;
}no[4*N];
LL a[N], sum[N];
int pre[N], last[N]; 
///pre保存第i个位置上的元素上一次出现的位置,
///last保存第i个位置上的元素在前i个数中出现的最后位置

void Bulid(int left, int right, int root)
{
    int mid;

    no[root].left = left;
    no[root].right = right;

    if (left == right)
    {
        no[root].Max = pre[left];
        return ;
    }

    mid = (left+right)/2;

    Bulid(left, mid, root*2);
    Bulid(mid+1, right, root*2+1);

    no[root].Max = max(no[root*2].Max, no[root*2+1].Max);
}

int Query(int left, int right, int root)
{
    int mid;

    if (left == no[root].left && right == no[root].right)
        return no[root].Max;

    mid = (no[root].left+no[root].right)/2;

    if (right <= mid) return Query(left, right, root*2);
    else if (left > mid) return Query(left, right, root*2+1);
    else return max(Query(left, mid, root*2), Query(mid+1, right, root*2+1));
}

int main ()
{
    int n, m, i, l, r, ans;
    LL s;

    while (scanf("%d%d", &n, &m) != EOF)
    {
        sum[0] = 0;
        for (i = 1; i <= n; i++)
            pre[i] = last[i] = 0;

        for (i = 1; i <= n; i++)
        {
            scanf("%lld", &a[i]);
            sum[i] = sum[i-1]+a[i];
        }

        for (i = 1; i <= n; i++)
        {
            pre[i] = last[a[i]];
            last[a[i]] = i;
        }

        Bulid(1, n, 1);

        while (m--)
        {
            scanf("%d%d", &l, &r);

            ans = Query(l, r, 1);

            s = (r-l+2)*(r-l+1)/2;

            if (ans < l && sum[r]-sum[l-1] == s) printf("YES
");
            else printf("NO
");
        }
    }

    return 0;
}
原文地址:https://www.cnblogs.com/syhandll/p/4982323.html