zoukankan      html  css  js  c++  java
  • poj 3368 Frequent values(RMQ)

    题意:给出一个非降序的数组,给出Q个询问,每个询问给出起点和终点,问在这个区间中出现频率最多的数字的次数。

    思路:这题可以用线段树,不过最近在学RMQ,所以用ST做的。这题的难点在于初始化,初始化后直接套模板就行了,来说说初始化吧。

    一个区间会出现三种情况:

    1、1111111111111,整个区间都被同一个数字占据,那么直接返回(r-l+1)就行了,

    2、1111122222222,整个区间只由开始和结尾两种数字组成,这种情况返回两者中较大的。

    3、11111222233333,区间中除了两头的数字还有其他数字,那么就用ST求出最大值就行了。

    对于每个数字出现的次数,用两个数组来存,一个数组存到目前为止这个数字出现了几次,另一个数组存这个数字总共出现了几次。呃,讲的不是很清楚,可以看代码。

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <queue>
    #define  N 100004
    using namespace std ;
    
    int a[N] , b[N] , mx[N][22] , dat[N] ;
    int n , q ;
    
    int maxs ( int x , int y )
    {
        return x > y ? x : y ;
    }
    
    void init()
    {
        int i , j , m ;
        m = floor( log( (double)n ) / log( 2.0));
        for ( i = 1 ; i <= n ; i++ )
        mx[i][0] = a[i] ;
        for ( i = 1 ; i <= m ; i++ )
        {
            for( j = 1 ; j + ( 1<<(i-1)) - 1 <= n ; j++ )
            mx[j][i] = maxs( mx[j][i-1] , mx[j+(1<<(i-1))][i-1] ) ;
        }
    }
    
    int find( int l , int r )
    {
        if ( a[r] >= ( r - l + 1 )) return ( r - l + 1);
        int m = maxs( b[l] - a[l] + 1 , a[r] );
        int k = 0 ;
        l = l + b[l] - a[l] + 1;
        r = r - a[r] ;
        if ( l > r ) return m ;
        while( l + ( 1<<k ) < r - ( 1<<k ) +1 ) ++k;
        return maxs( m , maxs( mx[l][k] , mx[r-(1<<k)+1][k] ));
    }
    
    int main()
    {
        int i , s , e ;
    
        while( scanf( "%d" , &n ) != EOF )
        {
            if( n == 0 )
            break ;
            scanf( "%d" , &q );
            for( i = 1 ; i <= n ; i++ )
            {
                scanf( "%d" , &dat[i] );
                a[i] = 1 ;
            }
            for( i = 2 ; i <= n ; i++ )
            {
                if( dat[i] == dat[i-1] )
                a[i] = a[i-1] + 1;
            }
            b[n] = a[n] ;
            for ( i = n - 1 ; i >= 1 ; i-- )
            {
                if ( dat[i] == dat[i+1] )
                b[i] = b[i+1] ;
                else
                b[i] = a[i] ;
            }
            init();
            while( q-- )
            {
                scanf( "%d%d" , &s , &e );
                printf( "%d\n" , find( s , e ));
            }
        }
        return 0 ;
    }
  • 相关阅读:
    NSDate
    Info.plist字段列表详解
    面向对象编程思想以及强、弱引用总结
    分类(类别/Category)与 类扩展(Extension)
    UIAlertView
    SQLite3的运用
    快速创建单例
    C++ 常用设计模式
    I2S 总线学习:2-I2S驱动WM8978
    设计模式的七大原则
  • 原文地址:https://www.cnblogs.com/misty1/p/2625141.html
Copyright © 2011-2022 走看看