POJ2892——Tunnel Warfare(Treap)

Tunnel Warfare
Time Limit: 1000MS Memory Limit: 131072K
Total Submissions: 9165 Accepted: 3786
Description

During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.

Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!

Input

The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.

There are three different events described in different format shown below:

D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
Output

Output the answer to each of the Army commanders’ request in order on a separate line.

Sample Input

7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
Sample Output

1
0
2
4
Hint

An illustration of the sample input:

  OOOOOOO

D 3 OOXOOOO

D 6 OOXOOXO

D 5 OOXOXXO

R OOXOOXO

R OOXOOOO
Source

POJ Monthly–2006.07.30, updog
题目:这里写链接内容
题意:给定一个序列,删除一些点,询问x所在区间的最长连续长度,每次恢复操作会还原最近一次被删除的点。
思路:用Treap维护被删除的点的的序列,每次询问,查询x的前后驱即可。恢复操作使用栈储存,用Treap删除。
代码:

#include <cstdio>
#include <algorithm>
#include <ctime>
#include <limits.h>
#include <stack>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 30100;


struct Treap {

    struct node {
        ll key, weight, cnt, size;
        node *childs[2];

        void init(ll x) {
            key = x;
            weight = rand();//配合srand((long long)time(NULL));使用
            cnt = 1;
            size = 1;
            childs[0] = childs[1] = NULL;
        }
    };

    node *root;

    void update(node *&x) {
        if (x == NULL)
            return;
        ll right = 0, left = 0;
        if (x->childs[0] != NULL)right = x->childs[0]->size;
        if (x->childs[1] != NULL)left = x->childs[1]->size;
        x->size = right + left + x->cnt;
    }

    void rotate(node *&x, int t) {
        node *y = x->childs[t];
        x->childs[t] = y->childs[1 - t];
        y->childs[1 - t] = x;
        update(x);
        update(y);
        x = y;
    }

    void _insert(node *&x, ll k) {
        if (x != NULL) {
            if (x->key == k) {
                x->cnt = 1;
            } else {
                int t = x->key < k;
                _insert(x->childs[t], k);
                if (x->childs[t]->weight < x->weight) {
                    rotate(x, t);
                }
            }
        } else {
            x = (node *) malloc(sizeof(node));
            x->init(k);
        }
        update(x);
    }

    void _erase(node *&x, ll k) {
        if (x == NULL)return;
        if (x->key == k) {
            if (x->cnt > 1) {
                x->cnt--;
            } else {//如果被删除节点存在子节点,先将其旋转至底层再删除
                if (x->childs[0] == NULL && x->childs[1] == NULL) {
                    x->cnt = 0;
                    return;
                }
                int t;
                if (x->childs[0] == NULL)t = 1;
                else if (x->childs[1] == NULL)t = 0;
                else t = x->childs[0]->weight > x->childs[1]->weight;
                rotate(x, t);
                _erase(x, k);
            }
        } else {
            int t = x->key < k;
            if (x->childs[t] != NULL)_erase(x->childs[t], k);//如果树中不存在k则可能搜索到空节点造成RE
            if (x->childs[t] != NULL && x->childs[t]->cnt == 0)free(x->childs[t]), x->childs[t] = NULL;//动态内存释放
        }
        update(x);
    }

    ll _getkth(node *&x, ll k) {
        ll t = 0;
        if (x->childs[0] != NULL)t = x->childs[0]->size;
        if (k <= t)return _getkth(x->childs[0], k);
        k -= t + x->cnt;
        if (k <= 0)return x->key;
        return _getkth(x->childs[1], k);
    }

    void _upper(node *&x, ll k, ll &ans) {
        if (x->key <= k) {
            ans = max(ans, x->key);
            if (x->childs[1] != NULL)_upper(x->childs[1], k, ans);
        } else if (x->childs[0] != NULL)_upper(x->childs[0], k, ans);
    }

    void _lower(node *&x, ll k, ll &ans) {
        if (x->key >= k) {
            ans = min(ans, x->key);
            if (x->childs[0] != NULL)_lower(x->childs[0], k, ans);
        } else if (x->childs[1] != NULL)_lower(x->childs[1], k, ans);
    }

    void _count(node *&x, ll k, ll &ans) {
        if (x == NULL)return;//如果root==NULL 则可能RE
        if (x->key >= k) {
            ans -= x->cnt;
            if (x->childs[1] != NULL)ans -= x->childs[1]->size;
            if (x->childs[0] != NULL)_count(x->childs[0], k, ans);
        } else if (x->childs[1] != NULL)_count(x->childs[1], k, ans);
    }

    void insert(ll k) {
        _insert(root, k);
    }

    void erase(ll k) {
        _erase(root, k);
        if (root != NULL && root->cnt == 0)free(root), root = NULL;//释放根节点
    }

    ll getkth(ll k) {
        if (root == NULL || k > root->size)return -1;//不存在第K大的情况
        return _getkth(root, k);
    }

    void upper(ll k, ll &ans) {//找到不大于k的最大的数,ans初始化应为无限小,应保证存在大于等于K的数
        _upper(root, k, ans);
    }

    void lower(ll k, ll &ans) {//找到不小于k的最小的数,ans初始化无限大,保证存在比小于等于k的数
        _lower(root, k, ans);
    }

    void count(ll k, ll &ans) {//找比K小的数的个数
        _count(root, k, ans);
    }
};

Treap tree;

int main() {
    ll n, q;
    stack<ll> s;
    scanf("%lld%lld", &n, &q);
    tree.insert(0);
    tree.insert(n + 1);
    for (int i = 0; i < q; ++i) {
        char c;
        ll a;
        scanf(" %c", &c);
        if (c == 'D') {
            scanf("%lld", &a);
            tree.insert(a), s.push(a);
        } else if (c == 'Q') {
            scanf("%lld", &a);
            ll l = -1, r = n + 2;
            tree.upper(a, l);
            tree.lower(a, r);
            if (r == l)r++;
            printf("%lld\n", r - l - 1);
        } else {
            ll x = s.top();
            s.pop();
            tree.erase(x);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/swust5120160705/article/details/80197985