poj 3368

线段树

/*
 * 思路:在线段树的结点内设5个变量l、r、mx、lf、rf,[l,r]表示该结点的区间范围,
 * lf和rf分别表示元素a[l]和a[r]在区间内的出现频率,mx表示区间内的最高出现频率。
 * 假设区间[x,y]和[y+1,z]均被询问[i,j]覆盖,则可以分情况讨论区间[x,z]的mx值:
 * 若a[y]==a[y+1],则mx[x,y]=max{mx[x,y],mx[y+1,z],rf[x,y]+lf[y+1,z]}
 * 否则mx[x,y]=max{mx[x,y],mx[y+1,z]}
 *
 */

代码:

#include<iostream>
#include<fstream>

using namespace std;

struct e{
	int l,r,maxx,maxl,maxr;
}tree[800000];
int n;
int a[100001];

void build(int l,int r,int p){
	int i,j,k;
	tree[p].l=l;
	tree[p].r=r;
	tree[p].maxl=0;
		tree[p].maxr=0;
		for(k=l;k<=r;k++)
			if(a[k]==a[l])
				tree[p].maxl++;
		for(k=r;k>=l;k--)
			if(a[k]==a[r])
				tree[p].maxr++;
	
	if(l<r){
		int mid=(l+r)>>1;

		build(l,mid,p*2);
		build(mid+1,r,p*2+1);
		if(a[mid]==a[mid+1])
			tree[p].maxx=max(tree[2*p].maxx,max(tree[2*p+1].maxx,tree[2*p].maxr+tree[2*p+1].maxl));
		else
			tree[p].maxx=max(tree[2*p].maxx,tree[2*p+1].maxx);
	}
	else
	{
		tree[p].maxx=1;
	}
}
int b[200001];

int find(int l,int r,int p){
	if(l==tree[p].l&&r==tree[p].r)
		return tree[p].maxx;
	int mid=(tree[p].l+tree[p].r)>>1;
	if(r<=mid)
		return find(l,r,p*2);
	if(l>mid)
		return find(l,r,p*2+1);
	if(a[mid]==a[mid+1])
	{
		int j=0,k=0;
		for(int i=mid;i>=l;i--)
			if(a[mid]==a[i])
				j++;
			else
				break;
		for(int i=mid+1;i<=r;i++)
			if(a[i]==a[mid+1])
				k++;
			else
				break;
		return max(find(l,mid,p*2),max(find(mid+1,r,2*p+1),j+k));
	}
	else
		return max(find(l,mid,p*2),find(mid+1,r,p*2+1));
}

void read(){
//	ifstream cin("in.txt");
	int i,j,k,s=0,t;
	while(1){
//		cin>>n;
		scanf("%d",&n);
		s=0;
		if(n==0) return;
//		cin>>k;
		scanf("%d",&k);
		memset(b,0,sizeof(b));
		for(i=1;i<=n;i++)
		{
//			cin>>j;
			scanf("%d",&j);
			if(b[j+100000]==0)
				b[j+100000]=++s;
			a[i]=b[j+100000];
		}
		build(1,n,1);
		for(i=1;i<=k;i++)
		{
//			cin>>j>>t;
			scanf("%d%d",&j,&t);
			cout<<find(j,t,1)<<endl;
		}
	}


}


int main(){
	read();
	return 0;
}

posted on 2011-03-07 11:29  宇宙吾心  阅读(242)  评论(0)    收藏  举报

导航