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..r−l+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 ( 1≤n,m≤1000000 ), 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 ( 1≤ai≤n ) 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 ( 1≤l≤r≤n ), indicating the query range.
Output:
For each query, if there is a permutation [1..r−l+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\n"); else printf("NO\n"); } } return 0; }