HDU 5172 GTY'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]里面,那么这一段区间就不是1~R-L+1 的全排列。

  所以我们可以O(n) 处理位置为i 的数x 的前一个数的位置 pre[i] 。

  用线段树维护这个pre[i] 的区间最大值。在[L, R] 这个区间的pre[i] 的最大值如果在[L, R] , 就NO。

  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <vector>
 8 #include <queue>
 9 #include <map>
10 #include <stack>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 typedef unsigned long long uLL;
15 #define ms(a, b) memset(a, b, sizeof(a))
16 #define rep(a, b) for(int a = 0;a<b;a++)
17 #define rep1(a, b) for(int a = 1;a<=b;a++)
18 #define pb push_back
19 #define mp make_pair
20 #define eps 0.0000000001
21 #define IOS ios::sync_with_stdio(0);cin.tie(0);
22 const LL INF = 0x3f3f3f3f3f3f3f3f;
23 const int inf = 0x3f3f3f3f;
24 const int mod = 1e9+7;
25 const int maxn = 1000000+10;
26 int n, m, x, l, r;
27 int pre[maxn], now[maxn];
28 LL sum[maxn];
29 int maxv[4*maxn];
30 int query(int ql, int qr, int o, int L, int R)
31 {
32     int M = (L+R)>>1;
33     int ans = -1;
34     if(ql <= L && R <= qr)  return maxv[o];
35     if(ql <= M) ans = max(ans, query(ql, qr, o*2, L, M));
36     if(M < qr)  ans = max(ans, query(ql, qr, o*2+1, M+1, R));
37     return ans;
38 }
39 void update(int o, int L, int R)
40 {
41     if(L==R){
42         maxv[o] = pre[L];
43         return;
44     }
45     int M = (L+R)>>1;
46     update(o*2, L, M);
47     update(o*2+1, M+1, R);
48     maxv[o] = max(maxv[o*2], maxv[o*2+1]);
49 }
50 void solve()
51 {
52     ms(now, 0);sum[0] = 0;
53     for(int i = 1;i<=n;i++){
54         scanf("%d", &x);
55         sum[i] = sum[i-1] + 1LL*x;
56         pre[i] = now[x];
57         now[x] = i;
58     }
59     update(1,1,n);
60     while(m--){
61         scanf("%d%d",&l, &r);
62         LL len = 1LL*(r-l+1);
63         if(sum[r]-sum[l-1] != len*(len+1)/2){
64             printf("NO\n");continue;
65         }
66         int Max = query(l, r, 1, 1, n);
67         if(Max<l){
68             printf("YES\n");
69         }
70         else{
71             printf("NO\n");
72         }
73     }
74 }
75 int main() {
76 #ifdef LOCAL
77     freopen("input.txt", "r", stdin);
78 //        freopen("output.txt", "w", stdout);
79 #endif
80 //    IOS
81     while(~scanf("%d%d", &n, &m))
82         solve();
83     return 0;
84 }

HDU 5172 GTY's gay friends (线段树)

时间: 2024-12-18 06:43:06

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(线段树最值)

题意: 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

BestCoder Round #29 1003 (hdu 5172) GTY&#39;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 o

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说明区

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

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 1394 Minimum Inversion Number(线段树)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10853    Accepted Submission(s): 6676 Problem Description The inversion number of a given number sequence a1, a2, ..., a

HDU 4902 (牛叉的线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c