zoukankan      html  css  js  c++  java
  • HDU 5172 GTY's gay friends 线段树

    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 [1..rl+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

    【题意】

    给出一个数列,询问连续的从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 }
    View Code
  • 相关阅读:
    中国石油大学天梯赛真题模拟第三场
    中国石油大学天梯赛真题模拟第一场
    PTA 水果忍者
    演练3-1:留言管理系统的制作
    知识点4-1:哪些应该放在动作方法中?
    Week5(10月11日):国庆后补课的复杂心情
    知识点3-5:使用强类型模板
    Week5(10月10日):国庆之后,让我们整装期待元旦吧
    知识点3-6:HTML辅助方法
    知识点3-4:给视图传递数据
  • 原文地址:https://www.cnblogs.com/jcf94/p/4294284.html
Copyright © 2011-2022 走看看