HDU 5091 扫描线,线段树

题意:给n个点,和长w宽h的矩形,问矩形最多能包含多少个点(边界也算)。


1、离散化;

2、考虑点(x,y),那么右上角为{  (x,y)~(x+W,y+H) }的矩形可以覆盖点(x,y);

     于是对于点(x,y)转化成线段(x , y , y+H , 进来1)  , (x+W+1 , y , y+h , 出去0)   ,   这里y+H+1一样效果;

3、按y轴建立线段树,维护最大值;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		new HDU5091().solve();
	}
}

class HDU5091 {

	InputReader in = new InputReader(System.in);
	PrintWriter out = new PrintWriter(System.out);
	final int N = 20008 ;
	int[] lx = new int[N] ;
	int[] rx = new int[N] ;
	int[] ly = new int[N] ;
	int[] ry = new int[N] ;
	int[] x = new int[N<<1] ;
	int[] y = new int[N<<1] ;
	Line[] line = new Line[N<<1] ;
	
	SegmentTree tree = new SegmentTree() ;

	void solve() {
		 int w , h  , n , xsize , ysize ; 
		 while(true){
			 n = in.nextInt() ;
			 if(n < 0) break ; 
			 w = in.nextInt() ;
			 h = in.nextInt() ;
			 xsize = ysize = 0 ;
			 for(int i = 0 ; i < n ; i++){
				 lx[i] = in.nextInt() ;
				 ly[i] = in.nextInt() ;
				 rx[i] = lx[i] + w + 1 ;
				 ry[i] = ly[i] + h  ;
				 x[xsize++] = lx[i] ;
				 x[xsize++] = rx[i] ;
				 y[ysize++] = ly[i] ;
				 y[ysize++] = ry[i] ;
			 }
			 
			 Arrays.sort(x , 0 , xsize) ;
			 Arrays.sort(y , 0 , ysize) ;
			 int[] X = Std.unique(x , 0 , xsize) ;
			 int[] Y = Std.unique(y , 0 , ysize) ;
			 
			 for(int i = 0 ; i < n ; i++){
				 lx[i] = Std.upper_bound(X , lx[i]) ;
				 rx[i] = Std.upper_bound(X , rx[i]) ;
				 ly[i] = Std.upper_bound(Y , ly[i]) ;
				 ry[i] = Std.upper_bound(Y , ry[i]) ;
			 }
			 
			 int lineSize = 0 ;
			 for(int i = 0 ; i < n ; i++){
				 line[lineSize++] = new Line(lx[i] , ly[i] , ry[i] , 1) ;
				 line[lineSize++] = new Line(rx[i] , ly[i] , ry[i] , -1) ;
			 }
			 Arrays.sort(line , 0 , lineSize) ;
			 
			 tree.build(1 , 1 , Y.length) ;
			 int res = 0 ;
			 for(int i = 0 ; i < lineSize ; i++){
				 tree.update(line[i].l , line[i].r , line[i].val , 1 , 1 , Y.length) ;
			     res = Math.max(res , tree.max[1]) ;
			 }
			 out.println(res) ;
		 }
		
         out.flush() ;
	}
}

class Line implements Comparable<Line>{
	int x , l , r , val ;
	Line(int x , int l , int r , int val){
		this.x = x ;
		this.l = l ;
		this.r = r ;
		this.val = val ;
	}
	
	@Override
	public int compareTo(Line other){
		if(x != other.x) return Integer.compare(x , other.x) ;
		return Integer.compare(val , other.val) ;
	}
	
	@Override
	public String toString() {
		return "Line [x=" + x + ", l=" + l + ", r=" + r + ", val=" + val + "]";
	}
}

class SegmentTree{
	final int N = 20008 ;
	int[] max = new int[N<<2] ;
	int[] add = new int[N<<2] ;
	
	void build(int root , int l , int r){
		max[root] = add[root] = 0 ;
	    if(l == r) return ;
	    int m = (l + r) >> 1 ;
	    build(root<<1 , l , m) ;
	    build(root<<1|1 , m+1 , r) ;
	    up(root) ;
	}
	
	void down(int root){
		if(add[root] != 0){
			add[root<<1] += add[root] ;
			max[root<<1] += add[root] ;
			add[root<<1|1] += add[root] ;
			max[root<<1|1] += add[root] ;
			add[root] = 0 ;
		}
	}
	
	void up(int root){
		max[root] = Math.max(max[root<<1] , max[root<<1|1]) ;
	}
	
	void update(int L , int R , int val , int root , int l , int r){
		if(L <= l && r <= R){
			max[root] += val ;
			add[root] += val ;
			return ;
		}
		down(root) ;
		int m = (l + r) >> 1 ;
		if(L <= m) update(L , R , val , root<<1 , l , m) ;
		if(R > m)  update(L , R , val , root<<1|1 , m+1 , r) ;
		up(root) ;
	}
}

class Std{
	static int[] unique(int[] array , int l , int r){
		if(l == r) return new int[0] ;
		int size = 1 ;
		for(int i = l+1 ; i < r ; i++){
			if(array[i] != array[i-1]) size++ ;
		}
		int[] res = new int[size] ;
		int idx = 0 ;
		res[idx++] = array[l] ;
		for(int i = l+1 ;  i < r ; i++){
			if(array[i] != array[i-1]) res[idx++] = array[i] ;
		}
		return res ;
	}
	
	static int[] unique(int[] array){
		return unique(array , 0 , array.length) ;
	}
	
	static int upper_bound(int[] array , int l , int r , int val){
		int res = r , m ;
		r-- ;
		while(l <= r){
			m = (l + r) >> 1 ;
		    if(array[m] > val){
		    	res = m ;
		    	r = m - 1 ;
		    }
		    else l = m + 1 ;
		}
		return res ;
	}
	
	static int upper_bound(int[] array , int val){
		return upper_bound(array , 0 , array.length , val) ;
	}
}

class InputReader {
	public BufferedReader reader;
	public StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream), 32768);
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}

	public BigInteger nextBigInteger() {
		return new BigInteger(next());
	}

}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值