Frequent values【线段树】

Frequent values

 UVA - 11235 

题目传送门

题目大意:给出一个非降序的整数数组a1,a2,a3...an,你的任务是对一系列的询问(i,j),回答ai,ai+1,ai+2...aj中出现次数最多的值所出现的次数。输入包括多组数据。每组数据第一行为两个整数n和q(1<=n,q<=100000)。第二行包含n个非降序排列的整数a1,a2,a3...an(-100000<=ai<=100000),以下q行每行包括两个整数i和j(1<=i<=j<=n),输入以0结束。

解决方法:用value[i]和Count[i]分别表示第i段的数值和出现的次数,num[p],Left[p],Right[p]分别表示位置p所在段的编号和左右端点的位置,所以(i,j)的答案就是取Right[i]-i+1,j-Left[j]+1,query(1,t,1,num[i]+1,num[j]-1)的最大值。

AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
int arr[maxn];
int maxl[maxn];
int value[maxn];
int Count[maxn];
int Left[maxn];
int Right[maxn];
int num[maxn];
void pushup(int x)
{
	maxl[x]=max(maxl[x<<1],maxl[x<<1|1]);
}
void build(int l,int r,int x)
{
	if(l==r)
	{
		maxl[x]=Count[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,x<<1);
	build(mid+1,r,x<<1|1);
	pushup(x);
}
int query(int l,int r,int x,int L,int R)
{
	int ans=0;
	if(L<=l&&r<=R)
		return maxl[x];
	int mid=(l+r)>>1;
	if(L<=mid)
		ans=max(ans,query(l,mid,x<<1,L,R));
	if(R>mid)
		ans=max(ans,query(mid+1,r,x<<1|1,L,R));
	return ans;
}
int main() 
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    //freopen("out.txt", "w", stdout);
    ios::sync_with_stdio(0),cin.tie(0);
    int n,m;
    while(cin>>n&&n)
    {
    	cin>>m;
    	ms(maxl);ms(arr);
    	ms(value);ms(Count);ms(num);ms(Left);ms(Right);
    	int t=0;
    	int l1=1,r1=n;
    	rep(i,1,n) {
    		cin>>arr[i];
    		if(arr[i]!=arr[i-1]||i==1)
    		{
    			t++;
    			if(i!=1)
    				l1=i;
    		}
    		num[i]=t;
    		Count[t]++;
    		value[t]=arr[i];
    		Left[i]=l1;
    	}
    	lep(i,n,1) {
    		Right[i]=r1;
    		if(arr[i]!=arr[i-1])
    			r1=i-1;
    	}
    	build(1,t,1);
    	while(m--)
    	{
    		int a,b;
    		cin>>a>>b;
    		if(a==b)
    			cout<<1<<endl;
    		else {
	    		int ans=0;
	    		ans=query(1,t,1,num[a]+1,num[b]-1);
	    		int nape;
	    		if(Right[a]==Right[b])
	    			nape=b-a+1;
	    		else
	    			nape=max(Right[a]-a+1,b-Left[b]+1);
	    		ans=max(ans,nape);
	    		cout<<ans<<endl;
	    	}
    	}
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值