poj3368--线段树统计区间的最大频率

5 篇文章 0 订阅
2 篇文章 0 订阅

今天又做了点图论和线段树的题目,比较有感触的就是这道,一开始感觉有点像hotel那道题,感觉记录区间的左右值和左右的最大频率以及总的最大频率即可,最后比较取最大,

后来在初始化的时候RE了一次,然后就AC了,感觉线段树终于入门了


import java.io.*;

public class Main {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(
			new InputStreamReader(System.in)));
	static  PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	final static  int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}
	
	class Node
	{
		int left,right;
		int lenum,rignum;//信息域,存储该区间的左右端的元素是什么
		int num,lnum,rnum;//存储左端的长度和右端长度以及最长的
		
		Node(int left,int right)
		{
			this.left=left;
			this.right=right;
		}
		
		int mid()
		{
			return (right+left)>>1;
		}
		int lenght()
		{
			return (right-left+1);
		}
	}
	static int number;
	static int MAX=100010;
	static Node tree[]=new Node[MAX<<2];
	static int data[]=new int[MAX];

	 void build(int left,int right,int idx) throws IOException
	{
//		 System.out.println(idx+"&^&^&");
		tree[idx]=new Node(left,right);
		tree[idx].left=left;
		tree[idx].right=right;
		if(tree[idx].left==tree[idx].right)
		{
			tree[idx].lenum=tree[idx].rignum=data[left];
//			System.out.println(data[left]);
			tree[idx].lnum=tree[idx].rnum=tree[idx].num=1;
			return;
		}
		
		int mid=tree[idx].mid();
		build(left,mid,idx<<1);
		build(mid+1,right,idx<<1|1);
		
		tree[idx].num=tree[idx<<1].num;
		if(tree[idx<<1|1].num>tree[idx].num)
			tree[idx].num=tree[idx<<1|1].num;
		
		if(tree[idx<<1].rnum+tree[idx<<1|1].lnum>tree[idx].num&&tree[idx<<1].rignum==tree[idx<<1|1].lenum)
		{
			tree[idx].num=tree[idx<<1].rnum+tree[idx<<1|1].lnum;
		}
		
		tree[idx].lenum=tree[idx<<1].lenum;
		tree[idx].rignum=tree[idx<<1|1].rignum;
		tree[idx].lnum=tree[idx<<1].lnum;
		tree[idx].rnum=tree[idx<<1|1].rnum;
		
		if(tree[idx<<1].lnum==tree[idx<<1].lenght()&&tree[idx<<1].rignum==tree[idx<<1|1].lenum)
			tree[idx].lnum=tree[idx<<1].lnum+tree[idx<<1|1].lnum;
		if(tree[idx<<1|1].rnum==tree[idx<<1|1].lenght()&&tree[idx<<1|1].lenum==tree[idx<<1].rignum)
			tree[idx].rnum=tree[idx<<1|1].rnum+tree[idx<<1].rnum;
	}
	
	int query(int a,int b,int idx)
	{
//		System.out.println("idx"+idx);
		if(tree[idx].left==a&&tree[idx].right==b)
		{

			return tree[idx].num;
		}
		
		int mid=tree[idx].mid();
//		System.out.println("MID"+mid);
		int ans1=-1,ans2=-1,ans3=-1,ans=-1;
		if(mid>=b)
		{
			return query(a,b,idx<<1);
		}else if(mid<a)
		{
			return query(a,b,idx<<1|1);
		}
		else
		{
			int temp1=query(a,mid,idx<<1);
			int temp2=query(mid+1,b,idx<<1|1);
			ans3=Math.max(temp1,temp2);
			int temp=-1;
			if(tree[idx<<1].rignum==tree[idx<<1|1].lenum)
			{
				if(mid-tree[idx<<1].rnum+1>=a)
				{
					a=mid-tree[idx<<1].rnum+1;
				}
				if(mid+tree[idx<<1|1].lnum<=b)
					b=mid+tree[idx<<1|1].lnum;
				
				
				temp=b-a+1;
			}
			ans3=Math.max(ans3, temp);
		return ans3;
	}
	}
	
	 void run() throws IOException
	{
		 
		while((number=nextInt())!=0)
		{
			int qnum=nextInt();
			for(int i=1;i<=number;i++)
				data[i]=nextInt();
			build(1,number,1);
			for(int i=1;i<=qnum;i++)
			{
				int a=nextInt();
				int b=nextInt();
				int ans=query(a,b,1);
				System.out.println(ans);
			}
			
		}
		
		
	}
	
	 public static void main(String[] args) throws IOException {
		
		 new Main().run();
		 
	}
	 	
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值