下午開始寫,編寫邊看動漫,果然寫挫了,,晚上來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() ;
}
}