☆【平衡二叉树】魔兽争霸

小 x正在销魂地玩魔兽
他正控制着死亡骑士和 n个食尸鬼(编号1~n)去打猎
 
死亡骑士有个魔法,叫做“死亡缠绕” ,可以给食尸鬼补充HP战斗过程中敌人会对食尸鬼实施攻击,食尸鬼的HP会减少
 
小 x希望随时知道自己部队的情况,即HP 值第 k多的食尸鬼有多少 HP,以便决定如何施放魔法
请同学们帮助他:)
 
小 x向你发出 3种信号: (下划线在输入数据中表现为空格)
A_i_a 表示敌军向第 i 个食尸鬼发出了攻击,并使第 i 个食尸鬼损失了 a 点HP,如果 它的 HP<=0,那么这个食尸鬼就死了(Undead 也是要死的……)。
敌军不会攻击一个已死的食尸鬼。
C_i_a 表示死亡骑士向第i个食尸鬼放出了死亡缠绕, 并使其增加了a点HP。  
HP值没有上限。
死亡骑士不会向一个已死的食尸鬼发出死亡缠绕
Q_k   表示小 x向你发出询问
 
输入(war.in)  
第一行,一个正整数 n
以后 n个整数 表示 n个食尸鬼的初始HP 值
接着一个正整数 m
以下 m行 每行一个小 x发出的信号
 
输出(war.out)  
对于小 x的每个询问,输出HP 第 k多的食尸鬼有多少HP,如果食尸鬼总数
不足k个,输出-1。每个一行数。
最后一行输出一个数:战斗结束后剩余的食尸鬼数
 
唐山一中NOIP2005模拟赛(2)  - 3 -
 
样例
Input
5
1 2 3
4 5
10
Q 2
A 4 6
C 1 4
Q 2
A 2 1
A 3 3
A 1 3
Q 4
C 2 10
Q 1

Output
4
5
-1
11
3
 
约定
40%的数据  n<=3000  m<=5000
70%的数据  n<=8000  m<=10000
100%的数据  n<=30000  m<=50000
90%的数据随机生成
食尸鬼HP没有上限
数据保证任意时刻食尸鬼的HP值在 longint范围内
数据保证 A和C命令中的食尸鬼是活着的
输入数据中没有多余空格、换行

標準的SBT,沒啥可多說的。

Accode:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <bitset>

const char fi[] = "war.in";
const char fo[] = "war.out";
const int maxN = 100010;
const int MAX = 0x3fffff00;
const int MIN = -MAX;

int lc[maxN], rc[maxN];
int c[maxN], key[maxN], sz[maxN];
int n, m, tot, T;

void init_file()
{
    freopen(fi, "r", stdin);
    freopen(fo, "w", stdout);
}

inline void R_Rotate(int &T)
{
    int tmp = lc[T];
    lc[T] = rc[tmp];
    rc[tmp] = T;
    sz[tmp] = sz[T];
    sz[T] = sz[lc[T]] + sz[rc[T]] + 1;
    T = tmp;
}

inline void L_Rotate(int &T)
{
    int tmp = rc[T];
    rc[T] = lc[tmp];
    lc[tmp] = T;
    sz[tmp] = sz[T];
    sz[T] = sz[lc[T]] + sz[rc[T]] + 1;
    T = tmp;
}

void Maintain(int &T, bool flag)
{
    if (!flag)
    {
        if (sz[lc[lc[T]]] > sz[rc[T]])
            R_Rotate(T);
        else if (sz[rc[lc[T]]] > sz[rc[T]])
        {
            L_Rotate(lc[T]);
            R_Rotate(T);
        }
        else return;
    }
    else
    {
        if (sz[rc[rc[T]]] > sz[lc[T]])
            L_Rotate(T);
        else if (sz[lc[rc[T]]] > sz[lc[T]])
        {
            R_Rotate(rc[T]);
            L_Rotate(T);
        }
        else return;
    }
    Maintain(lc[T], false);
    Maintain(rc[T], true);
    Maintain(T, false);
    Maintain(T, true);
}

inline int Select(int &T, int k)
{
    if (k == sz[lc[T]] + 1) return key[T];
    if (k <= sz[lc[T]]) return Select(lc[T], k);
    else return Select(rc[T], k - sz[lc[T]] - 1);
}

inline int Del(int &T, int v)
{
  --sz[T];
  if (key[T] == v
    || v < key[T] && !lc[T]
    || v > key[T] && !rc[T])
  {
    int tmp = key[T];
    if (!lc[T] || !rc[T]) T = lc[T] + rc[T];
    else key[T] = Del(lc[T], key[T] + 1); //
    return tmp;
  }
  if (v < key[T]) return Del(lc[T], v);
  else return Del(rc[T], v);
}

inline void insert(int &T, int v)
{
    if (!T)
    {
        key[T = ++tot] = v;
        sz[T] = 1;
        return;
    }
    ++sz[T];
    if (v < key[T]) insert(lc[T], v);
    else insert(rc[T], v);
    Maintain(T, v >= key[T]);
}

void readdata()
{
    scanf("%d", &n);
    for (int i = 1; i < n + 1; ++i)
    {
        scanf("%d", c + i);
        insert(T, c[i]);
    }
}

void work()
{
    scanf("%d", &m);
    for (; m; --m)
    {
        int x, delta;
        switch (getchar(), getchar())
        {
        case 'A':
            scanf("%d%d", &x, &delta);
            Del(T, c[x]);
            c[x] -= delta;
            if (c[x] > 0) insert(T, c[x]);
            break;
        case 'C':
            scanf("%d%d", &x, &delta);
            Del(T, c[x]);
            c[x] += delta;
            insert(T, c[x]);
            break;
        case 'Q':
            scanf("%d", &x);
            if (x > sz[T]) printf("-1\n");
            else printf("%d\n", Select(T, sz[T] - x + 1));
            break;
        }
    }
    printf("%d", sz[T]);
}

int main()
{
    init_file();
    readdata();
    work();
    exit(0);
}
第二次做:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>

const int maxN = 500010;

int lc[maxN], rc[maxN], key[maxN], sz[maxN];
int hp[maxN], T, top;

inline void Zig(int &T)
{
    int tmp = lc[T];
    lc[T] = rc[tmp];
    rc[tmp] = T;
    sz[tmp] = sz[T];
    sz[T] = sz[lc[T]] + sz[rc[T]] + 1;
    T = tmp;
    return;
}

inline void Zag(int &T)
{
    int tmp = rc[T];
    rc[T] = lc[tmp];
    lc[tmp] = T;
    sz[tmp] = sz[T];
    sz[T] = sz[lc[T]] + sz[rc[T]] + 1;
    T = tmp;
    return;
}

void Maintain(int &T, bool flag)
{
    if (!flag)
    {
        if (sz[lc[lc[T]]] > sz[rc[T]])
            Zig(T);
        else if (sz[rc[lc[T]]] > sz[rc[T]])
        {Zag(lc[T]); Zig(T);}
        else return;
    }
    else
    {
        if (sz[rc[rc[T]]] > sz[lc[T]])
            Zag(T);
        else if (sz[lc[rc[T]]] > sz[lc[T]])
        {Zig(rc[T]); Zag(T);}
        else return;
    }
    Maintain(lc[T], 0); Maintain(rc[T], 1);
    Maintain(T, 0); Maintain(T, 1);
    return;
}

void Ins(int &T, int v)
{
    if (!T)
    {
        sz[T = ++top] = 1;
        key[T] = v;
        return;
    }
    ++sz[T];
    if (v < key[T]) Ins(lc[T], v);
    else Ins(rc[T], v);
    Maintain(T, v >= key[T]);
    return;
}

int Select(int T, int k)
{
    if (k == sz[lc[T]] + 1)
        return key[T];
    if (k <= sz[lc[T]])
        return Select(lc[T], k);
    else return Select(rc[T], k - sz[lc[T]] - 1);
}

int Del(int &T, int v)
{
    --sz[T];
    if (v == key[T]
        || v < key[T] && !lc[T]
        || v > key[T] && !rc[T])
    {
        int tmp = key[T];
        if (!lc[T] || !rc[T])
            T = lc[T] + rc[T];
        else key[T] = Del(lc[T], key[T] + 1);
        return tmp;
    }
    if (v < key[T]) return Del(lc[T], v);
    else return Del(rc[T], v);
}

inline int getint()
{
    int res = 0; char tmp;
    while (!isdigit(tmp = getchar()));
    do res = (res << 3) + (res << 1) + tmp - '0';
    while (isdigit(tmp = getchar()));
    return res;
}

int main()
{
    freopen("war.in", "r", stdin);
    freopen("war_SBT.out", "w", stdout);
    int n = getint();
    for (int i = 1; i < n + 1; ++i)
        Ins(T, hp[i] = getint());
    for (int m = getint(), x; m; --m)
    switch (scanf("\n"), getchar())
    {
    case 'A':
        Del(T, hp[x = getint()]);
        hp[x] -= getint();
        if (hp[x] > 0) Ins(T, hp[x]);
        break;
    case 'C':
        Del(T, hp[x = getint()]);
        Ins(T, hp[x] += getint());
        break;
    case 'Q':
        printf("%d\n", (x = sz[T] - getint() + 1)
               > 0 ? Select(T, x) : -1);
        break;
    }
    printf("%d\n", sz[T]);
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值