GTY's gay friends
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
【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
in
, print 'YES', else print 'NO'.
in
, 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
【题意】
给出一个数列,询问连续的从l开始到r为止的数是否刚好能够组成从1开始到r-l+1的数列。
【分析】
每一次询问都是一个区间询问。
对于每一个区间询问,需要判断区间内的数是否刚好可以组成1到k的连续数列,主要的判断标准有两个:
1.区间数字的总和与(1+k)*k/2相等;
2.保证区间内所有数都只出现一次。
第一个可以在读入数据时用前缀和解决。
第二个就要用到线段树了,读入时预处理记录下与当前数相同的数最近一次出现的位置。询问l~r的区间时,检索每个数的最近出现位置位置,若得到的所有结果都在区间左端的左边,那就说明区间中所有的数都是不重复出现的,则满足条件。这里就是用线段树判断区间最大值小于区间左端的过程了。
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : G++ 4 PROG : HDU5172 5 ************************************************ */ 6 7 #include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 #include <algorithm> 11 12 using namespace std; 13 14 const int N=1e6+10; 15 16 int last[N],a,sum[N]; 17 18 typedef struct treetyp 19 { 20 int a,b,l,r,data; 21 } treetype; 22 treetype tree[2*N]; 23 int treetail; 24 25 void maketree(int l,int r) 26 { 27 treetail++; 28 int now=treetail; 29 tree[now].a=l; 30 tree[now].b=r; 31 if (l<r) 32 { 33 tree[now].l=treetail+1; 34 maketree(l,(l+r)/2); 35 tree[now].r=treetail+1; 36 maketree((l+r)/2+1,r); 37 } 38 } 39 40 void add(int n,int i,int data) 41 { 42 if (tree[n].data<data) tree[n].data=data; 43 if (i==tree[n].a&&i==tree[n].b) return ; 44 else if (i<=(tree[n].a+tree[n].b)/2) add(tree[n].l,i,data); 45 else add(tree[n].r,i,data); 46 } 47 48 int res; 49 50 void search(int n,int a,int b) 51 { 52 if (tree[n].a>=a&&tree[n].b<=b) 53 { 54 if (res<tree[n].data) res=tree[n].data; 55 return ; 56 } 57 if (tree[n].a==tree[n].b) return ; 58 if (a<=(tree[n].a+tree[n].b)/2) search(tree[n].l,a,b); 59 if (b>=(tree[n].a+tree[n].b)/2+1) search(tree[n].r,a,b); 60 } 61 62 int main() 63 { 64 int n,m; 65 while(scanf("%d%d",&n,&m)==2) 66 { 67 memset(sum,0,sizeof(sum)); 68 memset(last,0,sizeof(last)); 69 70 treetail=0; 71 maketree(1,n); 72 for (int i=1;i<=n;i++) 73 { 74 scanf("%d",&a); 75 sum[i]=sum[i-1]+a; 76 add(1,i,last[a]); 77 last[a]=i; 78 } 79 80 for (int i=1;i<=m;i++) 81 { 82 int l,r; 83 scanf("%d%d",&l,&r); 84 if ((r-l+1)*(r-l+2)/2==sum[r]-sum[l-1]) 85 { 86 res=0; 87 search(1,l,r); 88 if (res<l) printf("YES "); 89 else printf("NO "); 90 } else printf("NO "); 91 } 92 } 93 94 return 0; 95 }