• Frequent values(线段树+离散化)


    http://poj.org/problem?id=3368

    题意:给出一个非降序排列的整数数组,对于询问(i,j),输出区间[i,j]中出现最多的值的次数。

    思路:经典的RMQ,不过我用线段树做的。首先要离散化,因为是非降序的,所以相同的数是连续的,可以将相同的数分在同一个块中,将块中的信息存储起来,然后将其看成一个点,就可以用线段树进行查询了。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=1000010;
     6 struct node
     7 {
     8     int l,r;
     9     int Max;
    10 } Tree[N*4];
    11 struct point//记录每块的信息
    12 {
    13     int s,t;//s起始位置,t结束位置
    14     int cnt;//块中的数出现的次数
    15 } block[N];
    16 int v[N],num[N];//num[i]表示第i个数被分在第几块
    17 void build(int l,int r,int rt)
    18 {
    19     Tree[rt].l = l;
    20     Tree[rt].r = r;
    21     if (l==r)
    22     {
    23         Tree[rt].Max = block[l].cnt;
    24         return ;
    25     }
    26     int mid = (l+r)>>1;
    27     build(l,mid,rt<<1);
    28     build(mid+1,r,rt<<1|1);
    29     Tree[rt].Max=max(Tree[rt<<1].Max,Tree[rt<<1|1].Max);
    30 }
    31 int Query(int l,int r,int rt)
    32 {
    33     if(Tree[rt].l==l&&Tree[rt].r==r)
    34         return Tree[rt].Max;
    35     int mid=(Tree[rt].l+Tree[rt].r)>>1;
    36     if (r <= mid)
    37         return Query(l,r,rt<<1);
    38     else if (l > mid)
    39         return Query(l,r,rt<<1|1);
    40     else
    41         return max(Query(l,mid,rt<<1),Query(mid+1,r,rt<<1|1));
    42 }
    43 int main()
    44 {
    45     int n,q;
    46     while(~scanf("%d%d",&n,&q)&&n)
    47     {
    48         memset(block,0,sizeof(block));
    49         for (int i = 1; i <= n; i++)
    50             scanf("%d",&v[i]);
    51         int m=1;
    52         block[m].s=1;
    53         for (int i = 1; i <= n; i++)//将相同的数分在同一块
    54         {
    55             num[i]=m;
    56             if(v[i]!=v[i+1]||i==n)
    57             {
    58                 block[m].t = i;
    59                 block[m].cnt=block[m].t-block[m].s+1;
    60                 block[++m].s = i+1;
    61             }
    62         }
    63         build(1,m-1,1);//将每一块看成一个点,建树
    64         while(q--)
    65         {
    66             int l,r;
    67             scanf("%d%d",&l,&r);
    68             if (num[l]==num[r])//在同一个块里,则[l,r]是连续的相同的数
    69                 printf("%d
    ",r-l+1);
    70             else               //不在同一个块里
    71             {
    72                 int cnt1 = block[num[l]].t-l+1;//l所在块中,区间[l,block[num[l]].t]中相同的数的次数
    73                 int cnt3 = r-block[num[r]].s+1;//r所在块中,区间[block[num[r]].s,r]中相同的数的次数
    74                 int cnt2 = 0; 
    75                 if (num[r]-num[l]>1)//大于两个块
    76                     cnt2 = Query(num[l]+1,num[r]-1,1);//中间块相同数出现的最多次数
    77                 int ans = max(max(cnt1,cnt3),cnt2);
    78                 printf("%d
    ",ans);
    79             }
    80         }
    81     }
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    外观模式
    建造者模式
    原型模式
    工厂模式
    单例模式
    设计模式入门
    SpringBoot-SpringMVC开发总结
    SpringBoot日志
    IDEA Basics
    Kafka基础学习
  • 原文地址:https://www.cnblogs.com/lahblogs/p/3557967.html
Copyright © 2020-2023  润新知