zoukankan      html  css  js  c++  java
  • [UVa11235]Frequent values

    题目大意:给一个非降序排列的整数数组a,你的任务是对于一系列询问(i, j),回答ai,ai+1...aj中次数出现最多的值所出现的次数。

    解题思路:由于是非降序排列,所有相同的数都是连在一起的。

    本题可用RMQ做,但是我不会啊。 其实这题可以直接用线段树做(什么?RMQ可以用线段树做?我还是不会啊),不过需要保存三个东西,该区间出现最多的数出现的次数,该区间最左边的数出现的次数,该区间最右边出现的次数。

    为什么要保存左边和右边的出现次数呢?例如区间$[1,10]$分为区间$[1,5]$和$[6,10]$,那么$[1,5]$的右边就有可能和$[6,10]$的左边拼成一段出现次数更多的序列,所以要保存这两个值,并计算两个区间拼接后的最大值和原最大值哪个更优。查询时同理。

    C++ Code:

    #include<iostream>
    using namespace std;
    int n,m,a[100001];
    struct node{
    	int Ls,Rs,s;
    	node(int l=0,int r=0,int s=0):Ls(l),Rs(r),s(s){}
    }d[400004];
    inline int max(int a,int b){return(a>b)?a:b;}
    void bt(int l,int r,int o){
    	if(l==r){
    		d[o]=node(1,1,1);
    		return;
    	}
    	int mid=l+r>>1;
    	bt(l,mid,o<<1);
    	bt(mid+1,r,o<<1|1);
    	d[o].s=max(d[o<<1].s,d[o<<1|1].s);
    	if(a[mid]==a[mid+1])d[o].s=max(d[o].s,d[o<<1].Rs+d[o<<1|1].Ls);
    	//如果左子区间的最右边的值等于右子区间的最左边的值,那么两边就能拼起来,形成一个更长的段
    	d[o].Ls=d[o<<1].Ls;
    	d[o].Rs=d[o<<1|1].Rs;
    	if(a[mid]==a[mid+1]){
    		if(d[o].Ls==mid-l+1) 
    		d[o].Ls+=d[o<<1|1].Ls;
    		//如果左子区间的最右边的值等于右子区间的最左边的值,而左子区间刚好都是一个数,那么就能和右边拼起来 
    		if(d[o].Rs==r-mid)
    		d[o].Rs+=d[o<<1].Rs;
    		//右子区同理 
    	}
    }
    node query(int l,int r,int o,const int L,const int R,int ll,int rr){
    	if(L<=l&&r<=R)return d[o];
    	int mid=l+r>>1;
    	node ld,rd,nd;
    	if(L<=mid)ld=query(l,mid,o<<1,L,R,ll,mid);
    	if(mid<R)rd=query(mid+1,r,o<<1|1,L,R,mid+1,rr);
    	if(ld.s==0)return rd;
    	if(rd.s==0)return ld;
    	nd.s=max(ld.s,rd.s);
    	if(a[mid]==a[mid+1])
    	nd.s=max(nd.s,ld.Rs+rd.Ls);
    	nd.Ls=ld.Ls;
    	nd.Rs=rd.Rs;
    	if(a[mid]==a[mid+1]){
    		if(nd.Ls==mid-ll+1)
    		nd.Ls+=rd.Ls;
    		if(nd.Rs==rr-mid)
    		nd.Rs+=ld.Rs;
    	}
    	return nd;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	while(cin>>n>>m){
    		for(int i=1;i<=n;++i)cin>>a[i];
    		bt(1,n,1);
    		while(m--){
    			int x,y;
    			cin>>x>>y;
    			cout<<query(1,n,1,x,y,x,y).s<<endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    scripting.dictionary的彻底研究
    希望老人江诗信
    JavaScript正则表达式
    ASP日期和时间函数示例
    Asp网页制作技巧
    常见URL字符及URL编码值
    ASP.NET中如何调用存储过程
    【网摘】C#处理Json的另外一种方式 拓荒者
    使用Lucene.net进行全文查找多关键字匹配 拓荒者
    C#通用类型转换 Convert.ChangeType 拓荒者
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7289322.html
Copyright © 2011-2022 走看看