SPOJ 3261. Race Against Time(RACETIME) 【线段树套SBT】

http://www.spoj.pl/problems/RACETIME/

题意:1、修改某个数;2、求区间内小于等于某个数的数有多少个。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 100010;

struct Node {
    int key, val;
    Node(){};
    Node(int a, int b) { key = a; val = b; }
    bool operator < (Node b)  { return val < b.val; }
    bool operator <= (Node b) { return val <= b.val; } 
    bool operator > (Node b)  { return val > b.val; }
    bool operator >= (Node b) { return val >= b.val; }
    bool operator == (Node b) { return val == b.val; }
    Node operator + (int a) {
        return Node(key, val+a) > Node(key, val) ? Node(key, val+a) : Node(key, val-a);
    }
};

int sz[maxn*30];
int key[maxn*30];
int lch[maxn*30];
int rch[maxn*30];
int tot;

template<typename Type>
class SBT
{
public:
    SBT() { Clear(); }
	void Clear() { root = 0; lch[0] = rch[0] = sz[0] = 0; }
	static void ClearAll() { tot = 0; }
    int Size() { return sz[root]; }
    bool Empty() { return 0 == sz[root]; }
    bool Find(Type k) { return Find(root, k); }
    void InsertR(Type k) { Insert(root, k); } // 可重复插入 
    void Insert(Type k) { if (!Find(k)) Insert(root, k); }
    void Delete(Type k) { if (Find(k)) Delete(root, k); }
    void DeleteSmaller(Type k) { DeleteSmaller(root, k); }
    int GetRank(Type k) { return GetRank(root, k); }
    Type GetKth(int k) { return GetKth(root, k); }
    Type GetMin() { return GetKth(root, 1); }
    Type GetMax() { return GetKth(root, Size()); }
    Type GetPre(Type k) { return GetPre(root, k); }
    Type GetSuc(Type k) { return GetSuc(root, k); }
    int GetSmaller(Type k) { return GetSmaller(root, k); } // 返回小于k的元素的个数 
    
private:
    void LeftRotate(int &t) {
        int k = rch[t];
        rch[t] = lch[k];
        lch[k] = t;
        sz[k] = sz[t];
        sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
        t = k;
    }
    void RightRotate(int &t) {
        int k = lch[t];
        lch[t] = rch[k];
        rch[k] = t;
        sz[k] = sz[t];
        sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
        t = k;
    }
    void Maintain(int &t, bool flag) {
        if (0 == t) return ;
        if (false == flag) {
            if (sz[lch[lch[t]]] > sz[rch[t]]) {
                RightRotate(t);
            } else if (sz[rch[lch[t]]] > sz[rch[t]]) {
                LeftRotate(lch[t]);
                RightRotate(t);
            } else {
                return ;
            }
        } else {
            if (sz[rch[rch[t]]] > sz[lch[t]]) {
                LeftRotate(t);
            } else if (sz[lch[rch[t]]] > sz[lch[t]]) {
                RightRotate(rch[t]);
                LeftRotate(t);
            } else {
                return ;
            }
        }
        Maintain(lch[t], false);
        Maintain(rch[t], true);
        Maintain(t, false);
        Maintain(t, true);
    }
    Type GetPre(int t, Type k) {
        if (0 == k) return k;
        if (k <= key[t]) return GetPre(lch[t], k);
        Type tmp = GetPre(rch[t], k);
        if (tmp == k) return key[t];
        return tmp;
    }
    Type GetSuc(int t, Type k) {
        if (0 == root) return k;
        if (k >= key[t]) return GetSuc(rch[t], k);
        Type tmp = GetSuc(lch[t], k);
        if (tmp == k) return key[t];
        return tmp;
    }
    Type GetKth(int t, int k) {
        if (sz[lch[t]] >= k) return GetKth(lch[t], k);
        if (sz[lch[t]] == k - 1) return key[t];
        return GetKth(rch[t], k - sz[lch[t]] - 1);
    }
    int GetRank(int t, Type k) {
        if (0 == t) return 0;
        if (k < key[t]) return GetRank(lch[t], k);
        return sz[lch[t]] + 1 + GetRank(rch[t], k);
    }
    int GetSmaller(int t, Type k) {
        if (0 == t) return 0;
        if (k <= key[t]) return GetSmaller(lch[t], k);
        return sz[lch[t]] + 1 + GetSmaller(rch[t], k);
    }
    bool Find(int t, Type k) {
        if (0 == t) return false;
        else if (k < key[t]) return Find(lch[t], k);
        else return (key[t] == k || Find(rch[t], k));
    }
    void Insert(int &t, Type k) {
        if (0 == t) {
            t = ++tot;
            lch[t] = rch[t] = 0;
            sz[t]= 1;
            key[t] = k;
            return ;
        }
        sz[t]++;
        if (k < key[t]) Insert(lch[t], k);
        else Insert(rch[t], k);
        Maintain(t, k >= key[t]);
    }
	void DeleteSmaller(int &t , Type k) {
		if (0 == t) return ;
		if ( key[t] < k ) {
			t = rch[t];
			DeleteSmaller(t , key);
		} else {
			DeleteSmaller(lch[t] , k);
			sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
		}
	}
    Type Delete(int &t, Type k) {
        sz[t]--;
        if ((key[t] == k) || (k < key[t] && 0 == lch[t]) || (k > key[t] && 0 == rch[t])) {
            Type tmp = key[t];
            if (0 == lch[t] || 0 == rch[t]) {
                t = lch[t] + rch[t];
            } else {
                key[t] = Delete(lch[t], key[t] + 1);
            }
            return tmp;
        } else {
            if (k < key[t]) {
                return Delete(lch[t], k);
            } else {
                return Delete(rch[t], k);
            }
        }
    }
private:
	int root;
};

SBT<int> sbt[maxn<<2];
int n, q;
int a[maxn];

void Build(int l, int r, int rt)
{
    sbt[rt].Clear();
    for (int i = l; i <= r; ++i) {
        sbt[rt].InsertR(a[i]);
    }
    if (l == r) return ;
    int mid = (l + r) >> 1;
    Build(l, mid, rt << 1);
    Build(mid + 1, r, (rt << 1) | 1);
}

void Update(int l, int r, int rt, int p, int c)
{
    sbt[rt].Delete(a[p]);
    sbt[rt].InsertR(c);
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (p <= mid) {
        Update(l, mid, rt << 1, p, c);
    } else {
        Update(mid + 1, r, (rt << 1) | 1, p, c);
    }
}

int Query(int l, int r, int rt, int L, int R, int X)
{
    if (L <= l && R >= r) {
        return sbt[rt].GetRank(X);
    }
    int mid = (l + r) >> 1;
    if (R <= mid) {
        return Query(l, mid, rt << 1, L, R, X);
    }
    if (L > mid) {
        return Query(mid + 1, r, (rt << 1) | 1, L, R, X);
    }
    return Query(l, mid, rt << 1, L, mid, X) + Query(mid + 1, r, (rt << 1) | 1, mid + 1, R, X);
}

inline bool get(int &a)  
{  
    char c;  
    while(((c=getchar())<'0'||c>'9')&&c!=EOF);  
    if(c==EOF)return 0;  
    for(a=0;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';  
    return 1;  
}

int main()
{
    //freopen("racetime.in", "r", stdin);
    //freopen("racetime.out1", "w", stdout);
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; ++i) {
        //scanf("%d", &a[i]);
        get(a[i]); 
    }
    SBT<int>::ClearAll();
    Build(1, n, 1);
    char op[2];
    int x, y, z;
    while (q--) {
        scanf("%s", op);
        if (op[0] == 'C') {
            //scanf("%d%d%d", &x, &y, &z);
            get(x); get(y); get(z); 
            printf("%d\n", Query(1, n, 1, x, y, z));
        } else {
            //scanf("%d%d", &x, &y);
            get(x); get(y);
            Update(1, n, 1, x, y);
            a[x] = y;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值