BestCoder Round #29 1003 (hdu 5172) GTY's gay friends [线段树 判不同 预处理 好题]

传送门

GTY‘s gay friends

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 264    Accepted Submission(s): 57

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 a i

, 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≤100000

), 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 i th

number a i

( 1≤a i ≤n

) indicates GTY‘s i th

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

转自官方题解:http://bestcoder.hdu.edu.cn/

1003 GTY‘s gay friends
一个区间是排列只需要区间和为len(len+1)2  

(len 

为区间长度),且互不相同,对于第一个问题我们用前缀和解决,对于第二个问题,预处理每个数的上次出现位置,记它为pre,互不相同即区间中pre的最大值小于左端点,使用线段树或Sparse Table即可在O(n)/O(nlogn) 

的预处理后 O(logn)/O(1) 

回答每个询问.不过我们还有更简单的hash做法,对于[1..n] 

中的每一个数随机一个64位无符号整型作为它的hash值,一个集合的hash值为元素的异或和,预处理[1..n] 

的排列的hash和原序列的前缀hash异或和,就可以做到线性预处理,O(1) 

回答询问.
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<string>
 12
 13 #define N 1000005
 14 #define M 105
 15 #define mod 10000007
 16 //#define p 10000007
 17 #define mod2 1000000000
 18 #define ll long long
 19 #define LL long long
 20 #define eps 1e-6
 21 #define inf 100000000
 22 #define maxi(a,b) (a)>(b)? (a) : (b)
 23 #define mini(a,b) (a)<(b)? (a) : (b)
 24
 25 using namespace std;
 26
 27 ll n,m;
 28 ll a[N];
 29 ll f[N];
 30 ll pr[N];
 31 ll sum[N];
 32
 33 ll mapre[4*N];
 34
 35 ll build(ll i,ll l,ll r)
 36 {
 37     if(l==r){
 38         mapre[i]=pr[l];
 39         //printf(" i=%I64d l=%I64d mapre=%I64d pr=%I64d\n",i,l,mapre[i],pr[l]);
 40         return mapre[i];
 41     }
 42     ll mid=(l+r)/2;
 43     ll lm=build(2*i,l,mid);
 44     ll rm=build(2*i+1,mid+1,r);
 45     mapre[i]=max(lm,rm);
 46     //printf(" i=%I64d mapre=%I64d\n",i,mapre[i]);
 47     return mapre[i];
 48 }
 49
 50 ll query(ll i,ll L,ll R,ll l,ll r)
 51 {
 52     if(l>=L && r<=R){
 53         return mapre[i];
 54     }
 55     ll mid=(l+r)/2;
 56     ll lm,rm;
 57     lm=0;rm=0;
 58     if(L<=mid){
 59         lm=query(i*2,L,R,l,mid);
 60     }
 61     if(R>mid){
 62         rm=query(i*2+1,L,R,mid+1,r);
 63     }
 64     return max(lm,rm);
 65 }
 66
 67 void ini()
 68 {
 69     ll i;
 70     sum[0]=0;
 71     memset(f,0,sizeof(f));
 72     for(i=1;i<=n;i++){
 73         scanf("%I64d",&a[i]);
 74         sum[i]=sum[i-1]+a[i];
 75     }
 76     //for(i=0;i<=n;i++){
 77     //    printf(" i=%I64d sum=%I64d\n",i,sum[i]);
 78    // }
 79     for(i=1;i<=n;i++){
 80         pr[i]=f[ a[i] ];
 81         f[ a[i] ]=i;
 82     }
 83    // for(i=0;i<=n;i++){
 84    //     printf(" i=%I64d pr=%I64d\n",i,pr[i]);
 85    // }
 86     build(1,1,n);
 87 }
 88
 89 void solve()
 90 {
 91     ll x,y;
 92     ll ss;
 93     ll len;
 94     ll qu;
 95     while(m--){
 96         scanf("%I64d%I64d",&x,&y);
 97         len=y-x+1;
 98         ss=sum[y]-sum[x-1];
 99         //printf(" ss=%I64d sum=%I64d\n",ss,len*(len+1)/2);
100         if(ss==(len*(len+1)/2)){
101             qu=query(1,x,y,1,n);
102             if(qu<x){
103                 printf("YES\n");
104             }
105             else{
106                 printf("NO\n");
107             }
108         }
109         else{
110             printf("NO\n");
111         }
112     }
113 }
114
115 void out()
116 {
117
118 }
119
120 int main()
121 {
122     //freopen("data.in","r",stdin);
123     //freopen("data.out","w",stdout);
124     //scanf("%d",&T);
125     //for(int ccnt=1;ccnt<=T;ccnt++)
126    // while(T--)
127     //scanf("%d%d",&n,&m);
128     while(scanf("%I64d%I64d",&n,&m)!=EOF)
129     {
130         ini();
131         solve();
132         out();
133     }
134     return 0;
135 }

BestCoder Round #29 1003 (hdu 5172) GTY's gay friends [线段树 判不同 预处理 好题]

时间: 2024-10-05 05:58:29

BestCoder Round #29 1003 (hdu 5172) GTY's gay friends [线段树 判不同 预处理 好题]的相关文章

hdu 5172 GTY&#39;s gay friends 线段树

GTY's gay friends 问题描述 GTY有n个基友,出于某种恶趣味,GTY每天早上会让他的基友们排成一行,每个基友有一个特征值,表示基友有多雄壮或娘炮,你,作为GTY的助手,必须回答GTY的每个询问,GTY每次会问一个区间[l,r][l,r]是否为一个11到r-l+1r−l+1的排列. 输入描述 多组数据(约3组),每组数据的第一行有两个数n,m(1 \leq n,m \leq 100000)n,m(1≤n,m≤100000) 表示初始基友数量和询问个数,第二行包含nn个数a_i (

HDU 5172 GTY&#39;s gay friends (线段树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5172 题意: 给你一个n个数的数组,m次询问,询问在[L, R] 这个区间里面有没有 [1, R-L+1] 的数. 题解: 判断有没有 1 ~ R-L+1 其实就是判断这一段区间和是不是等于 (R-L+1)*(R-L+1+1)/ 2 . 当然还有就是每一个数只能出现1次. 这个问题我们应该怎么解决呢. 我们可以记录第i个数x 的前一个x出现的位置.如果x的前一个x也出现在[L, R]里面,那么这一段

HDU - 5172 GTY&#39;s gay friends

题目链接 题意:n个数m个查询,问[l,r]中的数是否为1到r-l+1的一个排列. 做法1:hash一下,对于[1...n],每个数都随机分配一个hash值,一个集合的hash值为元素异或和.预处理出[1...n]的hash值及其前缀的hash,然后就可以O(1)查询了 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib&g

hdu 5172 GTY&#39;s gay friends(线段树最值)

题意: GTY有n个朋友,站成一排,每个人有一个特征值ai. 有m个询问.每次询问给两个数L,R.问你[L,R](即aL...aR)是否是1..(R-L+1)的一个全排列. 是输出YES,否则输出NO 思路: 先判断是否segma(a[L,R])是否等于(R-L)*(R-L+1)/2. 记录每一个ai上一次的位置pre[i]. 这样只要判断a[L]...a[R]中的每一个pre[i]是否都小于L即可.(这个方法太妙) 线段树区间求最大值. *用map效率明显下降. 代码: int const N

HDU 5172 GTY&#39;s gay friends(线段树)

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 assista

HDU 5172 GTY&#39;s gay friends (预处理+线段树)

题目链接:HDU 5172 GTY's gay friends 题意:给出一串序列,询问[l,r]区间里是否存在1~l-r+1的一个排列. 思路:1~l-r+1的一个排列 等价于 [l,r]中元素互不相同且[l,r]区间和等于(1+len)*len/2(len=l-r+1). 区间和可以用前缀和来处理. 元素互不相同,记录位置i上a[i]上次出现的位置记做pre[i],再用线段树来维护区间的pre最大值,若最大值小于l说明[l,r]中元素互不相同.(区间[l,r]中的每个pre[i]小于l说明区

GTY&#39;s gay friends 线段树判断区间是否有相同数字

http://acm.hdu.edu.cn/showproblem.php?pid=5172 判断一个区间是否为全排列是: 1.区间总和 = (1 + R - L + 1) * (R - L + 1) / 2; 2.区间没有重复数字 记录数组a[i]表示第i个数上一次在那个位置出现. 那么最需要在[L, R]中a[i]的最大值 >= L的,就是有重复数字了. #include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false)

hdu 5171 GTY&#39;s birthday gift (BestCoder Round #29)

GTY's birthday gift                                                                       Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 209    Accepted Submission(s): 71 Problem Description F

BestCoder Round #29 1001 GTY&#39;s math problem

GTY's math problem Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description GTY is a GodBull who will get an Au in NOI . To have more time to learn alg