Poj 2892 Tunnel Warfare

一段区间上有一段连续的房子,每次可以消灭一个房子,修复一个房子,询问某一个房子所在的区间的长度


一个简单的线段树题

用splay写的话也很简单的,因为能正好对应splay的一些基本操作


(别人的板子是坠吼的

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 51234;
struct Node {
	Node*ch[2], *p;
	int size;
	Node() {
		size = 0;
	}
	bool d() {
		return this == p->ch[1];
	}
	void setc(Node*c, int d) {
		ch[d] = c;
		c->p = this;
	}
	void relax();
	void upd() {
		size = ch[0]->size + ch[1]->size + 1;
	}
} Tnull, *null = &Tnull;

Node mem[maxn];


Node *make(int v) {
    Node *C=&mem[v];
	C->ch[0] = C->ch[1] = null;
	C->size = 1;
	return C;
}

Node*build(int l, int r) {
	if (l > r)
		return null;
	int m = (l + r) >> 1;
	Node*t = make(m);
	t->setc(build(l, m-1), 0);
	t->setc(build(m + 1, r), 1);
	t->upd();
	return t;
}

Node*root;

void rot(Node*t) {
	Node*p = t->p;
	int d = t->d();
	p->p->setc(t, p->d());
	p->setc(t->ch[!d], d);
	t->setc(p, !d);
	p->upd();
	if (p == root)
		root = t;
}

void splay(Node*t, Node*f = null) {
	while (t->p != f) {
		if (t->p->p == f)
			rot(t);
		else
			t->d() == t->p->d() ? (rot(t->p), rot(t)) : (rot(t), rot(t));
	}
	t->upd();
}

int n;
int times[maxn];

void dist(int id){
    Node *rot = &mem[id];
    splay(rot);
    for(int i=0;i<2;i++){
        if(rot->ch[i] != null){
            rot->ch[i]->p=null;
            rot->ch[i]=null;
        }
    }
    rot->upd();
    times[id]++;
}

int query(int id){
    if(times[id] > 0)
        return 0;
    Node *rot = &mem[id];
    splay(rot);
    return rot->size;
}

void Link(int l,int r){
    Node *L = &mem[l];
    Node *R = &mem[r];
    splay(L);
    splay(R);
    L->setc(R,1);
    L->upd();
}

void fix(int id){
    times[id]--;
    if(times[id]!=0)
        return;
    if(id > 1 && times[id-1]==0){
       Link(id-1,id);
    }
    if(id < n && times[id+1]==0){
        Link(id,id+1);
    }
}

stack<int> S;

int main() {
    int m;
	while(~scanf("%d %d",&n,&m)){
        while(S.empty()==false)
            S.pop();
        memset(times,0,sizeof(times));
        root = build(1, n);
        root->p = null;
        char ord[4];
        int id;
        while(m--){
            scanf("%s",ord);
            if(*ord == 'R'){
                id = S.top();
                S.pop();
                fix(id);
            }
            else{
                scanf("%d",&id);
                if(*ord == 'Q'){
                    printf("%d\n",query(id));
                }
                else{
                    dist(id);
                    S.push(id);
                }
            }
        }
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值