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 ;
    }
  • 相关阅读:
    链表--判断一个链表是否为回文结构
    矩阵--“之”字形打印矩阵
    二叉树——平衡二叉树,二叉搜索树,完全二叉树
    链表--反转单向和双向链表
    codeforces 490C. Hacking Cypher 解题报告
    codeforces 490B.Queue 解题报告
    BestCoder19 1001.Alexandra and Prime Numbers(hdu 5108) 解题报告
    codeforces 488A. Giga Tower 解题报告
    codeforces 489C.Given Length and Sum of Digits... 解题报告
    codeforces 489B. BerSU Ball 解题报告
  • 原文地址:https://www.cnblogs.com/misty1/p/2625141.html
Copyright © 2011-2022 走看看