uva 11235 Frequent values

来源:互联网 发布:淘宝售后服务卡 编辑:程序博客网 时间:2024/06/09 19:03

题目:Frequent values


思路:

由于这一串数是不下降的,可以看出所有相等时的数都在一起。由此,可以把相同的几个数简化成一段数,设这一段数的值为这一段中数的个数。对于提问的一段,一般的可以分为3段:左边、右边两段不完整的,中间由几段完整的数拼起来的。也有分成2段不完整的,或只有一段不完整的情况,这些特殊处理即可。

还是说3段的那种一般情况,两边的可以直接计算,中间一段中的最小值用RMQ的ST。注意,此时d数组中存储的是每一段数的编号而不是每一个数的编号。


代码:

#include <cstdio>#include <iostream>#include <algorithm>#include <stack>#include <queue>#include <deque>#include <set>#include <cstring>#include <map>using namespace std;#define maxn 100005#define maxm 17int n,q;int a[maxn];int d[maxn][maxm];int v[maxn],cnt[maxn];//每一段的数值,编号int num[maxn];//每一个位置对应的段 int l[maxn],r[maxn];//每一段的最左,最右 int p;//段数 void Clear(){memset(d,0,sizeof(d));memset(cnt,0,sizeof(cnt));memset(a,0,sizeof(a));}void init(){//初始化 int w=0,t=0;//划分段 for(int i=1;i<=n+1;i++){if(a[i]!=w){w=a[i],t++;v[t]=w,cnt[t]++;num[i]=t,l[t]=i,r[t-1]=i-1;}else{cnt[t]++;num[i]=t;}}p=t-1;for(int i=1;i<=p;i++){ d[i][0]=cnt[i];}for(int j=1;(1<<j)<=p;j++){for(int i=1;i+(1<<j)-1<=p;i++){d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);}}}int find(int Lin,int Rin){//查询 int x=num[Lin],y=num[Rin];int L=x+1,R=y-1;int k=0;while((1<<k+1)<=R-L+1) k++;if(L>R&&x!=y) return max(r[x]-Lin+1,Rin-l[y]+1);//两段 if(x!=y) return max(max(d[L][k],d[R-(1<<k)+1][k]),max(r[x]-Lin+1,Rin-l[y]+1));//三段 return Rin-Lin+1;//一段 }int main() {while(~scanf("%d",&n)&&n!=0){Clear();scanf("%d",&q);for(int i=1;i<=n;i++){int x;scanf("%d",&x);a[i]=x;}init();for(int i=1;i<=q;i++){int x,y;scanf("%d%d",&x,&y);if(x>y) swap(x,y);printf("%d\n",find(x,y));}}return 0;}


原创粉丝点击