POJ2892地道战Tunnel Warfare(线段树)

点击打开题目链接对连续的村庄进行三种操作和问询

  1. D x: The x-th village was destroyed.
  2. Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
  3. R: The village destroyed last was rebuilt。
更新连续区间,若当前讯问区间内节点状态相同则返回当前区间连续值,否则根据当前查询点编号与左右区间的关系递归查询。

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

public class Main{
	class SegTree {
		class node {
			int left, right;
			int sum, lsum, rsum;
			int mid() {
				return (left + right) >>1;
			}
			int dis() {
				return (right - left + 1);
			}
			void init(int t) {
				sum = lsum = rsum = t *dis();
			}
		}

		node tree[];
		SegTree(int maxn) {
			tree = new node[maxn * 5];
		}

		void init(int left, int right, int idx) {
			tree[idx] = new node();
			tree[idx].left=left;
			tree[idx].right=right;
			tree[idx].init(1);
			if (left == right)
				return;
			int mid = tree[idx].mid();
			init(left, mid, idx << 1);
			init(mid + 1, right, (idx << 1)|1);
		}

		void update(int id, int v, int idx) {
			if (tree[idx].left == tree[idx].right) {
				tree[idx].init(v);
				return;
			}
			int mid = tree[idx].mid();
			if (id <= mid)
				update(id, v, idx << 1);
			else
				update(id, v, (idx << 1) + 1);
	        pushup(idx);		
		}

		int query(int id, int idx) {
			if (tree[idx].sum == 0|| tree[idx].sum == tree[idx].dis())
				return tree[idx].sum;
			int mid = tree[idx].mid();
			if (id <= mid) {
				if (id > mid - tree[idx << 1].rsum)
					return query(id, idx << 1) + query(mid + 1, (idx << 1) + 1);
				else
					return query(id, idx << 1);
			} else {
				if (id < mid + 1 + tree[(idx << 1)|1].lsum)
					return query(id, (idx << 1)|1) + query(mid, idx << 1);
				else
					return query(id, (idx << 1)|1);
			}
		}
		void pushup(int idx){
			int l = idx << 1;
			int r = (idx << 1)|1;
			tree[idx].sum = Math.max(tree[l].rsum + tree[r].lsum,
					Math.max(tree[r].sum, tree[l].sum));
			tree[idx].lsum = tree[l].lsum;
			tree[idx].rsum = tree[r].rsum;
			if (tree[l].sum == tree[l].dis())
				tree[idx].lsum += tree[r].lsum;
			if (tree[r].sum == tree[r].dis())
				tree[idx].rsum += tree[l].rsum;
		}
	} 
	StreamTokenizer in = new StreamTokenizer(new BufferedReader(
			new InputStreamReader(System.in)));

	final int next() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}
	void run() throws IOException {
		int n=next();
		int m=next();
		SegTree st=new SegTree(n);
		st.init(1,n, 1);
		int stack[]=new int[m];
		boolean des[]=new boolean[n+1];
		int top=0,k;
		while(m-->0){
			in.nextToken();
			String s=in.sval;
			if(s.charAt(0)=='D'){
				k=next();
				stack[++top]=k;
				des[k]=true;
				st.update(k,0,1);
			}
			if(s.charAt(0)=='Q'){
				k=next();
				if(des[k])
					System.out.println(0);
				else
					System.out.println(st.query(k,1));
			}
			if(s.charAt(0)=='R'){
				k=stack[top--];
				des[k]=false;
				st.update(k, 1, 1);
			}
		}
	}
	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、付费专栏及课程。

余额充值