uva11235 frequent values(Sparse Table)

xiaoxiao2021-02-28  80

题目链接:https://vjudge.net/problem/UVA-11235

题意:

给一个非降序的整数数组a,求[i, j]中出现最多次数的数,出现了几次。

思路:

明显的是RMQ问题。白书上用的是Sparse Table,这个叫ST表就变成了表表….

一开始思路就被定死,求出现最多的数出现的次数,感觉无从下手。看到刘汝佳的做法,还有这种操作….先进行游程编码,把相同的数压缩成一个点,对于所求的区间[i, j],那么i和j所对应的a[i]和a[j]必然属于某个对应的压缩后的点,对这些压缩后的点建树就可以了,维护最大值。

先判断i和j对应的区间是否相同,相同的话,答案就是j-i+1 否则为max( right[idx[i]] - i +1, j - left[idx[j]] +1, RMQ(idx[i]+1, idx[j]-1) ) idx[i]表示i所在的区间号,left为该区间的开始位置,right为该区间的结束位置。

竟然1A…

#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int maxn = 1e6 + 1000; int x, y, tmp; int num[maxn], lf[maxn], rg[maxn], val[maxn], cnt[maxn]; class SparseTable{ public: int **d, n, m; SparseTable(){} ~SparseTable(){ for(int i=0; i<n; ++i) delete []d[i]; delete []d; } int cal_len(int n){ return (int)(log(n*1.0)/log(2.0)); } void init(int A[], int n){ this->n = n; m = cal_len(n) + 200; d = new int*[n]; for(int i=0; i<n; ++i) d[i] = new int[m]; for(int i=0; i<n; ++i) d[i][0] = A[i]; for(int j=1; (1<<j)<=n; ++j){ for(int i=0; i+(1<<j)-1<n; ++i){ d[i][j] = max(d[i][j-1], d[i+(1<<(j-1))][j-1]); // minimal or maximal } } } int RMQ(int L, int R){ int k = 0; while((1<<(k+1)) <= R-L+1) ++k; return max(d[L][k], d[R-(1<<k)+1][k]); // minimal or maximal } }; int main(){ int n, q; ios::sync_with_stdio(false); while(cin>>n){ if(n==0) break; cin>>q; int pre=-maxn, tot=-1; memset(num, 0, sizeof(num)); memset(lf, 0, sizeof(lf)); memset(rg, -1, sizeof(rg)); memset(val, 0, sizeof(val)); memset(cnt, 0, sizeof(cnt)); for(int i=0; i<n; ++i){ cin>>tmp; if(tmp!=pre){ ++tot; val[tot] = tmp; cnt[tot]++; if(i-1>=0) rg[i-1] = i-1; lf[i] = i; pre = tmp; } else{ cnt[tot]++; lf[i] = lf[i-1]; } num[i] = tot; } rg[n-1] = n-1; for(int i=n-2; i>=0; --i){ if(rg[i]==-1) rg[i] = rg[i+1]; } SparseTable ST; ST.init(cnt, tot+1); for(int i=0; i<q; ++i){ cin>>x>>y; --x; --y; int no1 = num[x]; int no2 = num[y]; if(no1==no2){ cout<<y-x+1<<endl; } else{ int ans1 = rg[x] - x + 1; int ans2 = y - lf[y] + 1; int ans3; if(num[x]+1>num[y]-1){ ans3 = 0; } else{ ans3 = ST.RMQ(num[x]+1, num[y]-1); } cout<<max(max(ans1, ans2), ans3)<<endl; } } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-59861.html

最新回复(0)