POJ 3368 经典RMQ

来源:互联网 发布:诲女知之乎悔 编辑:程序博客网 时间:2024/05/21 08:02

下午开始写,编写边看动漫,果然写挫了,,晚上来debug,,,

题意:给一段不下降序列,,,求,l到r区间出现出现数字最多的数字的次数

思路:1,把相同的作为一段,num表示该下标所在的段,left表示该段最左边的下标,right表示该段最右边的下标,value表示改下标的值,fmax用于求各个段的最大值

2,一边情况是要求3段;l所在段;r所在段;在l和r中间的段(这段利用RMQ)  ;

#include <iostream>#include <cstdio>#include <cstring>#include <vector>using namespace std ;const int N = 100000 + 11 ;struct Process {int num[N] ; int left[N] ; int right[N] ;int value[N] ;int fmax[N][30] ;int n , m , q ;void addinfo() {n = 1 ;scanf("%d" ,&value[1]) ;left[1] = 1 , right[1] = 1 ;num[1] = 1 ;fmax[1][0] = 1 ;for(int i = 2 ; i <= m ; ++i) {scanf("%d" ,&value[i]) ;if(value[i] == value[i-1]) {right[n] = i ;num[i] = n ;++fmax[n][0] ;}else {++n ;left[n] = right[n] = i ;num[i] = n ;fmax[n][0] = 1 ;}}for(int i = 1 ; (1<<i)<= n ; ++i) {for(int j = 1 ; j+(1<<i)-1 <= n ; ++j) {fmax[j][i] = max(fmax[j][i-1] , fmax[j+(1<<(i-1))][i-1]) ;}}}void query(int l , int r) {if(num[l] == num[r]) {printf("%d\n" , r-l+1) ;return ;}int a1 = right[num[l]] - l + 1 ;int a2 = r - left[num[r]] + 1 ;l = num[l] + 1 ;r = num[r] - 1 ;if(r < l ) {printf("%d\n" , max(a1 , a2)) ;return ;}int k = 0 ;while((1<<(k+1))<=r-l+1) ++k ;int a3 = max(fmax[l][k] , fmax[r-(1<<k)+1][k]) ;printf("%d\n" , max(max(a1 , a2),a3)) ;}void std_fun() {addinfo() ;int l , r ;for(int i = 0 ; i < q ; ++i) {scanf("%d%d" ,&l ,&r) ;query(l , r) ;}}}p ;int main() {//freopen("data.in" ,"r" ,stdin) ;while(scanf("%d" ,&p.m)==1 && p.m) {scanf("%d" ,&p.q) ;p.std_fun() ;}}



0 0
原创粉丝点击