zoukankan      html  css  js  c++  java
  • UVA-11235 Frequent values (RMQ)

    题目大意:在一个长度为n的不降序列中,有m次询问,每次询问(i,j)表示在区间(i,j)中找出出现次数最多的元素的出现次数。

    题目分析:因为序列有序,可以将序列分段,并且记录每段的元素个数、每一个元素所属的段num(i)、每一个元素所属段的左端点l(i)及右端点r(i)。那么对于每次询问:

    ans(i,j)=max(max(r(i)-i+1,j-l(j)+1),rmq(num(i)+1,num(j)-1))。

    ans(i,j)=r-j+1  (如果i与j属于同一段)

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<vector>
    # include<queue>
    # include<list>
    # include<set>
    # include<map>
    # include<string>
    # include<cmath>
    # include<cstdlib>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int N=1005;
    const int INF=1000000000;
    const LL oo=0x7fffffffffffffff;
    const double eps=1e-10;
    
    int n,m;
    int a[N*100];
    vector<int>v;
    int num[N*100];
    int L[N*100];
    int R[N*100];
    int d[N*100][20];
    
    void RMQ_init()
    {
    	int len=v.size();
    	for(int i=0;i<len;++i) d[i][0]=v[i];
    	for(int j=1;(1<<j)<=len;++j)
    		for(int i=0;i+(1<<j)-1<len;++i)
    			d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    }
    
    void init()
    {
    	v.clear();
    	int cnt=1;
    	num[0]=0;
    	L[0]=0;
    	for(int i=1;i<n;++i){
    		if(a[i]==a[i-1]){
    			++cnt;
    			num[i]=num[i-1];
    			L[i]=L[i-1];
    		}else{
    			v.push_back(cnt);
    			num[i]=v.size();
    			L[i]=i;
    			cnt=1;
    		}
    	}
    	v.push_back(cnt);
    	R[n-1]=n-1;
    	for(int i=n-2;i>=0;--i){
    		if(a[i]==a[i+1])
    			R[i]=R[i+1];
    		else
    			R[i]=i;
    	}
    	RMQ_init();
    }
    
    int query(int l,int r)
    {
    	if(l>r) return 0;
    	int k=0;
    	while((1<<(k+1))<=r-l+1) ++k;
    	return max(d[l][k],d[r-(1<<k)+1][k]);
    }
    
    int solve(int l,int r)
    {
    	if(num[l]==num[r])
    		return r-l+1;
    	else{
    		return max(max(R[l]-l+1,r-L[r]+1),query(num[l]+1,num[r]-1));
    	}
    }
    
    int main()
    {
    	while(scanf("%d",&n)&&n)
    	{
    		scanf("%d",&m);
    		for(int i=0;i<n;++i)
    			scanf("%d",a+i);
    		init();
    		int l,r;
    		while(m--)
    		{
    			scanf("%d%d",&l,&r);
    			--l,--r;
    			printf("%d
    ",solve(l,r));
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    算法-经典趣题-寻找假银币
    一天一个 Linux 命令(3):cat 命令
    算法-经典趣题-青蛙过河
    常用数据库有哪些?
    SpringBoot2.0入门教程(一) 快速入门,项目构建HelloWorld示例
    一天一个 Linux 命令(2):ls 命令
    算法-经典趣题-爱因斯坦阶梯问题
    一天一个 Linux 命令(1):vim 命令
    什么是开发环境、测试环境、UAT环境、仿真环境、生产环境?
    算法-经典趣题-渔夫捕鱼
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5437086.html
Copyright © 2011-2022 走看看