POJ 3368 (ST表)

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

题意:给出n个连续单调不递减数,q次询问,每次询问区间(L,R)出现频率最多的数,问出现了多少次

思路:因为n个数是单调不递减的,所以可以预处理一个频率数组cnt[ ],cnt[ i ]记录某个数到 i 位置时,出现了多少次,再预处理一个index数字,记录每一段相同的数字,最右端的位置,因为每次询问的时候可能会出现一部分连续的数被L这个位置隔开,cnt[i]只记录了某个数到i位置出现了多少次,被隔开的部分多算了,所以需要减去,每次询问(L,R)的时候分为两个部分,前一部分查询出 index[ L ] - l为被隔开的部分,后一部分用st表维护区间最值求即可。

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue> 
 7 using namespace std;
 8 const int maxn = 100005;
 9 int n,q;
10 int a[maxn];
11 int cnt[maxn];
12 int index[maxn];
13 int Log[maxn];
14 int f[maxn][21];
15 void pre(){
16     Log[1] = 0;
17     Log[2] = 1;
18     for(int i =3;i<maxn;i++) Log[i] = Log[i/2] + 1; 
19 }
20 void st(){
21     for(int i = 1;i<=n;i++){
22         f[i][0] = cnt[i]; 
23     }
24     for(int j = 1;j<=Log[n+1];j++){
25         for(int i = 1;i+(1<<j)-1<=n;i++){
26             f[i][j] = max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
27         }
28     }
29 }
30 int main(){
31     pre();
32     while(~scanf("%d",&n)){
33     if(n == 0) break;
34     scanf("%d",&q);
35     for(int i = 1;i<=n;i++){
36         scanf("%d",&a[i]);
37         if(i == 1) cnt[i] = 1;
38         if(a[i]!=a[i-1]) cnt[i] = 1;
39         else cnt[i] = cnt[i-1] + 1;
40     }
41     st();
42     for(int i = n;i>=1;i--){
43         if(a[i] == a[i+1]) index[i] = index[i+1];
44         else index[i] = i;
45     }
46     while(q--){
47         int l,r;
48         int ans = 0;
49         scanf("%d%d",&l,&r);
50         if(index[l] == index[r]){
51             ans = r - l + 1;
52         }
53         else if(index[l] == index[l-1]){//判断一下,如果在l左边的数和l位置的数相等,就说明被隔开了 
54             int t = min(index[l],r)+1;//算出后一部分区间的左端点 
55             int ans1 = t - l ;//ans1单独计算 算出被隔开了多少数,这一部分单独计算 
56             int s = Log[r-t+1];//剩下部分用st表求 
57             ans = max(ans1,max(f[t][s],f[r-(1<<s)+1][s]));//两者取最大值 
58         }
59         else{
60             int s = Log[r-l+1];
61             ans = max(f[l][s],f[r-(1<<s)+1][s]);
62         }
63         printf("%d\n",ans);
64     }
65   }
66     return 0;
67 }
posted @ 2020-01-16 00:56  AaronChang  阅读(215)  评论(0编辑  收藏  举报