线段树——poj1823

题目:http://poj.org/problem?id=1823

大意是住宾馆,有三种操作,1是从第i个房间要连续入住m个人;2是从第i个房间要连续退房i个人;3是查询最大连续空房间数

很简单的线段树

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

class Tree{
	int ll, rr, mid;
	int max, cr, cl;
	int occ;
}

public class Main {
	Tree tree[];
	public Main(){
		tree = new Tree[32767];
		for (int i = 0; i < tree.length; i++)
			tree[i] = new Tree();
	}
	
	void push_down(int rt, int sign){
		tree[rt].occ = -1;
		tree[rt << 1].occ = tree[rt << 1|1].occ = sign;
		int r = rt << 1;
		if (sign == 1){
			tree[r].cl = tree[r].cr = tree[r+1].cl = tree[r+1].cr = 0;
			tree[r].max = tree[r+1].max = 0;
		}else{
			int len = tree[r].rr - tree[r].ll + 1;
			tree[r].cl = tree[r].cr = len;
			tree[r].max = len;
			len = tree[r+1].rr - tree[r+1].ll + 1;
			tree[r+1].cl = tree[r+1].cr =  len;
			tree[r+1].max = len;
					
		}
	}
	
	void build(int rt, int ll, int rr){
		tree[rt].ll = ll;
		tree[rt].rr = rr;
		tree[rt].max = tree[rt].cl = tree[rt].cr = rr - ll + 1;
		tree[rt].occ = 0;
		tree[rt].mid = (rr + ll) >> 1;
		
		if (ll < rr){
			build(rt << 1, ll, tree[rt].mid);
			build(rt << 1 | 1, tree[rt].mid + 1, rr);
		}
	}
	
	void update(int rt, int ll, int rr, int sign){
		if (tree[rt].ll == ll && tree[rt].rr == rr){
			tree[rt].occ = sign;
			int len = tree[rt].rr - tree[rt].ll + 1;
			if (sign == 1) len = 0;
			tree[rt].max = tree[rt].cl = tree[rt].cr = len;
			return ;
		}
		if (tree[rt].occ == 1){
			push_down(rt, 1);
		}
		if (tree[rt].occ == 0){
			push_down(rt, 0);
		}
		if (rr <= tree[rt].mid){
			update(rt << 1, ll, rr, sign);
		}else
		if (ll > tree[rt].mid){
			update(rt << 1 | 1, ll, rr, sign);
		}else {
			update(rt << 1, ll, tree[rt].mid, sign);
			update(rt << 1|1, tree[rt].mid+1, rr, sign);
		}
		
		if (tree[rt].occ == -1){
			if (tree[rt << 1].occ == 0){
				tree[rt].cl = tree[rt << 1].cl + tree[rt << 1 | 1].cl;
			}else tree[rt].cl = tree[rt << 1].cl;
			if (tree[rt << 1 |1].occ == 0){
				tree[rt].cr = tree[rt << 1|1].cr + tree[rt << 1].cr;
			}else tree[rt].cr = tree[rt << 1|1].cr;
			
			int len = tree[rt << 1].cr + tree[rt << 1|1].cl;
			tree[rt].max = Math.max(len, Math.max(tree[rt << 1].max, tree[rt<< 1|1].max));
		}else{
			int len ;
			
			if (sign == 1){
				len = 0;
			}else{
				len = tree[rt].rr - tree[rt].ll + 1;	
			}
			tree[rt].max = tree[rt].cl = tree[rt].cr = len;
		}
		if (tree[rt << 1].occ == tree[rt << 1|1].occ) tree[rt].occ = tree[rt << 1].occ;	
	}

	int getMax(){
		return tree[1].max;
	}
	
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		
		st.nextToken();
		
		int n = (int) st.nval;
		
		st.nextToken();
		int p = (int) st.nval;
		
		Main ma = new Main();
		int sign;
		int ll, rr;
		ma.build(1, 1, n);
		for (int i = 0; i < p; i++){
			st.nextToken();
			sign = (int) st.nval;
			if (sign == 3)
				System.out.printf("%d\n", ma.getMax());
			else{
				st.nextToken();
				ll = (int) st.nval;
				st.nextToken();
				rr = (int) st.nval;
				rr = ll + rr - 1;
				if (sign == 2) sign = 0;
				ma.update(1, ll, rr, sign);
			}
		}
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值