Uva 11235 Frequent values

来源:互联网 发布:id for mac中文破解版 编辑:程序博客网 时间:2024/04/30 03:32

求解一段区间内出现次数最多的数出现的次数。由于数列已经是非降序排列,因此可以采用游程编码来进行预处理。游程编码(Run Length Ecoding),用count[i]表示第i段的数值出现的次数,num[p],left[p],right[p]分别表示位置p所在段的编号和左右端点的位置。处理结束后,这就是一个RMQ问题,使用ST算法加以解决即可。每次询问[l, r]的结果都是以下三个部分的最大值:从l到l所在段的结束处的元素个数,从r所在段的开始到r处的元素个数,中间第num[l]+1段到num[r]-1段的count的最大值。

AC代码:

#include <math.h>#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int MAX = 100010;const int INF = 0x3f3f3f3f;int n,m,size;// the size of cnt[]int dp[MAX][30];int Count[MAX],num[MAX],Left[MAX],Right[MAX];int Max(int a, int b){return a > b ? a : b;}void RLE(){//游程编码int pre = INF, cur = -1;//the index of current segmentint x, l;//l is the Left boundary of current segmentfor(int i=0; i<n; i++){scanf("%d",&x);if(x == pre){Count[cur]++;num[i] = cur;Left[i] = l;}else{if(cur >= 0){for(int j=l; j<=i-1; j++)Right[j] = i-1;}cur++;// update the next segmentl = i;num[i] = cur;Left[i] = l;Count[cur] = 1;pre = x;}}for(int i=l; i<n; i++)Right[i] = n-1;size = cur + 1;}void ST(){//sparse-table算法int n = size;for(int i=0; i<n; i++) dp[i][0] = Count[i];int len = (int)(log((double)n)/log(2.0));for(int j=1; j<=len; j++)for(int i=0; i + (1 << j) -1 < n; i++)dp[i][j] = Max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);}int Query(int l, int r){//查询最大值if(l > r) return 0;int k = (int)(log((double)(r - l + 1))/log(2.0));return Max(dp[l][k], dp[r - (1<<k) + 1][k]);}int main(){while(scanf("%d",&n) == 1 && n){scanf("%d",&m);RLE();ST();while(m--){int l, r;scanf("%d%d",&l,&r);l--;r--;if(num[l] == num[r]) printf("%d\n",r - l + 1);else{int t1 = Right[l] - l + 1;int t2 = r - Left[r] + 1;int t3 = Query(num[l] + 1, num[r] - 1);printf("%d\n",Max(t3, Max(t1, t2)));}}}return 0;}


0 0
原创粉丝点击