HDU1806 Frequent values
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1806 Frequent values相关的知识,希望对你有一定的参考价值。
题解:
注意数组a是非降序排列。
所以将a数组转化出现次数的数组b
例如 -1 -1 2 3 对应 2 2 1 1
那么每次查询,分为左边,右边和中间三部分,
预处理每个数对应的左右范围.可以用map,也可以用二分。
代码:
//二分处理 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<map> #include<set> #include<vector> using namespace std; using namespace std; #define pb push_back #define mp make_pair #define se second #define fs first #define ll long long #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define ls o<<1 #define rs o<<1|1 #define SZ(x) ((int)(x).size()) #define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++) typedef pair<int,int> P; const double eps=1e-9; const int maxn=100100; const int N=1e9; const int mod=1e9+7; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } //----------------------------------------------------------------------------- int a[maxn],b[maxn],mx[maxn][20]; int n,m,k,l,r; map<int,int> Num; void rmq_init() { for(int i=1;i<=n;i++) mx[i][0]=b[i]; k=(int)(log(n*1.0)/log(2.0)); for(int i=1;i<=k;i++) for(int j=1;j<=n;j++){ mx[j][i]=mx[j][i-1]; if(j+(1<<(i-1))<=n) mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]); } } int rmq_max(int l,int r) { k=(int)(log((r-l+1.0)*1.0)/log(2.0)); return max(mx[l][k],mx[r-(1<<k)+1][k]); } int bs_left(int l) { int L=1,R=l,Goal=l; while(L<=R){ int M=(L+R)>>1; if(a[M]==a[l]){ Goal=M; R=M-1; } else L=M+1; } return Goal; } int bs_right(int r) { int L=r,R=n,Goal=r; while(L<=R){ int M=(L+R)>>1; if(a[M]==a[r]){ Goal=M; L=M+1; } else R=M-1; } return Goal; } int main(){ while(scanf("%d",&n)&&n){ scanf("%d",&m); Num.clear(); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); Num[a[i]]++; } for(int i=1;i<=n;i++) b[i]=Num[a[i]]; rmq_init(); for(int i=1;i<=m;i++){ scanf("%d%d",&l,&r); if(a[l]==a[r]) printf("%d\n",r-l+1); else{ int L_max=bs_right(l)-l+1; int R_max=r-bs_left(r)+1; int M_max=0; if(bs_right(l)+1<=bs_left(r)-1) M_max=rmq_max(bs_right(l)+1,bs_left(r)-1); printf("%d\n",max(max(L_max,R_max),M_max)); } } } return 0; }
以上是关于HDU1806 Frequent values的主要内容,如果未能解决你的问题,请参考以下文章
[HDOJ1806]Frequent values(RMQ,ST)
POJ 3368 Frequent values(线段树区间合并)