GTY's gay friends
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1695 Accepted Submission(s): 431
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
Source
题意:给你一个有n个数的序列,有q次询问,每次问区间[l,r]之间是否有1~(r-l+1)的所有数
解题思路:先求一下前缀和并预处理出每个位置的值之前出现的位置,然后根据每个位置的值之前出现的位置来建一棵线段树(或者求一下RMQ),每次询问时,先判断这段区间的和是否满足,然后再用线段树看出这段区间每个位置的值之前出现的位置是否小于l,若小于l,则满足,否则不满足
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <cmath>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
int n, q;
int a[1000200], pre[1000200], pos[1000200], x[1000200 * 4];
LL sum[1000200];
void build(int k,int l,int r)
{
if (l == r) { x[k] = pre[l]; return; }
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
x[k] = max(x[k << 1], x[k << 1 | 1]);
}
int query(int k,int l, int r,int ll,int rr)
{
if (l >= ll&&r <= rr) return x[k];
int mid = (l + r) >> 1;
int ma = -1;
if (ll <= mid) ma=max(ma,query(k << 1, l, mid, ll, rr));
if (rr > mid) ma=max(ma,query(k << 1 | 1, mid + 1, r, ll, rr));
return ma;
}
int main()
{
while (~scanf("%d%d", &n, &q))
{
memset(pos, -1, sizeof pos);
sum[0] = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
pre[i] = pos[a[i]];
pos[a[i]] = i;
sum[i]=sum[i-1]+1LL*a[i];
}
build(1,1,n);
while (q--)
{
int l, r;
scanf("%d%d", &l, &r);
if (sum[r] - sum[l - 1] != 1LL*(r - l + 2)*(r - l + 1) / 2) { printf("NO\n"); continue; }
if (query(1, 1, n, l, r)< l) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}