2018年东北农业大学春季校赛-L: wyh的天鹅(平衡树)

链接:https://www.nowcoder.com/acm/contest/93/L

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

你们wyh学长小时候住在河边,因为周围的生态环境非常好,所以经常会有天鹅浮在湖面上,每只天鹅都长得不一样,它们偶尔排成一排,偶尔分散开,偶尔也会去其他河畔,wyh学长为了统计它们的个数,编了一个程序赋予它们一个“萌”值,但是这些天鹅很不听话,一会儿会从别的地方游过来一两只,一会儿又会在统计过程中游走一两只,现在请你帮他完成统计任务。

输入描述:

共有T(T<=10)组数据,每组数据第一行为两个数 N, M (N,M <= 500000),代表有N只天鹅和M次操作,接下来一行是N个数字,下面M行首先会输入一个字符串S,接着会有三类操作,如果S是“insert”,接着输入一个正整数a,代表插入一只“萌”值为a的天鹅,如果S是“delete”,接着输入一个正整数a,代表删除一只“萌”值为a的天鹅,如果S是“query”,接着输入一个正整数k,代表查询“萌”值第k大的天鹅。
萌值为[1,1000000000],并且保证一定存在第k大

输出描述:

对应每次询问,输出询问结果。

示例1

输入

1
5 4
6 4 2 9 1
query 2
insert 7
delete 6
query 2

输出

6
7
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct SPLAY
{
    int val;
    int num,size;
    int f,l,r;
}a[2000000];
int root,size;
void show(int k)
{
    if(k==-1)return;
    printf("a[%d] father=%d  val=%d num=%d size=%d l=%d r=%d\n",k,a[k].f,a[k].val,a[k].num,a[k].size,a[k].l,a[k].r);
    show(a[k].l);
    show(a[k].r);
}
void maintain(int k)
{
    if(k==-1)return;
    a[k].size=a[k].num;
    if(a[k].l!=-1)a[k].size+=a[a[k].l].size;
    if(a[k].r!=-1)a[k].size+=a[a[k].r].size;
}
void right_rotate(int k)
{
    int p=a[k].f;
    a[k].f=a[p].f;
    if(a[p].f!=-1)
    {
        if(a[a[p].f].l==p)a[a[p].f].l=k;
        else a[a[p].f].r=k;
    }
    else root=k;
    a[p].l=a[k].r;
    if(a[k].r!=-1)a[a[k].r].f=p;
    a[k].r=p;
    a[p].f=k;
    maintain(p);
    maintain(k);
}
void left_rotate(int k)
{
    int p=a[k].f;
    a[k].f=a[p].f;
    if(a[p].f!=-1)
    {
        if(a[a[p].f].l==p)a[a[p].f].l=k;
        else a[a[p].f].r=k;
    }
    else root=k;
    a[p].r=a[k].l;
    if(a[k].l!=-1)a[a[k].l].f=p;
    a[k].l=p;
    a[p].f=k;
    maintain(p);
    maintain(k);
}
void splay(long long k,long long f)
{
    while(a[k].f!=f)
    {
        long long p=a[k].f;
        if(a[p].f==f)
        {
            if(a[p].l==k)right_rotate(k);
            else left_rotate(k);
        }
        else
        {
            long long ff=a[p].f;
            if(p==a[ff].l&&k==a[p].l)right_rotate(p),right_rotate(k);
            if(p==a[ff].l&&k==a[p].r)left_rotate(k),right_rotate(k);
            if(p==a[ff].r&&k==a[p].r)left_rotate(p),left_rotate(k);
            if(p==a[ff].r&&k==a[p].l)right_rotate(k),left_rotate(k);
        }
    }
}
void insert(int k,int val)
{
    if(k<0)
    {
        a[size].val=val;
        a[size].l=a[size].r=-1;
        a[size].f=-1;
        a[size].size=a[size].num=1;
        root=size;
        splay(size,-1);
        size++;
        return;
    }
    if(val<a[k].val)
    {
        if(a[k].l!=-1)insert(a[k].l,val);
        else
        {
            a[size].val=val;
            a[size].size=a[size].num=1;
            a[size].l=a[size].r=-1;
            a[size].f=k;
            a[k].l=size;
            splay(size,-1);
            size++;
        }
    }
    else if(val>a[k].val)
    {
        if(a[k].r!=-1)insert(a[k].r,val);
        else
        {
            a[size].val=val;
            a[size].size=a[size].num=1;
            a[size].l=a[size].r=-1;
            a[size].f=k;
            a[k].r=size;
            splay(size,-1);
            size++;
        }
    }
    else a[k].num++,a[k].size++,splay(k,-1);
    maintain(k);
}
int search(int k,int x)
{
    if(a[k].val>x)
    {
        if(a[k].l!=-1)return search(a[k].l,x);
    }
    else if(a[k].val<x)
    {
        if(a[k].r!=-1)return search(a[k].r,x);
    }
    splay(k,-1);
    maintain(k);
    return a[k].size-a[k].num+1-(a[k].r==-1?0:a[a[k].r].size);
}
int ask(int x)
{
    int k=root;
    while(1)
    {
         if(a[k].l!=-1&&x<=a[a[k].l].size)k=a[k].l;
         else
         {
            int temp=(a[k].l==-1?0:a[a[k].l].size)+a[k].num;
            if(x<=temp)return a[k].val;
            x-=temp;
            k=a[k].r;
         }
    }
    return 0;
}
int askpre(int k,int val)
{
    if(a[k].val>val)
    {
        if(a[k].l==-1)
        {
            long long p=a[k].f;
            while(p!=-1&&k==a[p].l)k=p,p=a[p].f;
            return p;
        }
        return askpre(a[k].l,val);
    }
    else if(a[k].val<val)
    {
        if(a[k].r==-1)return k;
        return askpre(a[k].r,val);
    }
    if(a[k].l==-1)
    {
        long long p=a[k].f;
        while(p!=-1&&k==a[p].l)k=p,p=a[p].f;
        return p;
    }
    k=a[k].l;
    while(a[k].r!=-1)k=a[k].r;
    return k;
}
int asknex(int k,int val)
{
    if(val<a[k].val)
    {
        if(a[k].l==-1)return k;
        return asknex(a[k].l,val);
    }
    else if(val>a[k].val)
    {
        if(a[k].r==-1)
        {
            int p = a[k].f;
            while( p!=-1&&k==a[p].r)k = p,p = a[p].f;
            return p;
        }
        return asknex(a[k].r,val);
    }
    if(a[k].r==-1)
    {
        int p = a[k].f;
        while( p!=-1&& k == a[p].r )k = p,p = a[p].f;
        return p;
    }
    k=a[k].r;
    while( a[k].l!=-1 )k = a[k].l;
    return k;
}
void Delete(int val)
{
    long long pre=askpre(root,val);
    long long nex=asknex(root,val);
    if(pre!=-1&&nex!=-1)
    {
        splay(pre,-1);
        splay(nex,pre);
        if(a[a[nex].l].num>1)a[a[nex].l].num--;
        else a[nex].l=-1;
        maintain(a[nex].l);
        maintain(nex);
        maintain(pre);
    }
    else if(pre!=-1&&nex==-1)
    {
        splay(pre,-1);
        if(a[pre].r!=-1&&a[a[pre].r].val==val)
        {
            if(a[a[pre].r].num>1)a[a[pre].r].num--;
            else a[pre].r=-1;
        }
        maintain(a[pre].r);
        maintain(pre);
    }
    else if(pre==-1&&nex!=-1)
    {
        splay(nex,-1);
        if(a[nex].l!=-1&&a[a[nex].l].val==val)
        {
            if(a[a[nex].l].num>1)a[a[nex].l].num--;
            else a[nex].l=-1;
        }
        maintain(a[nex].l);
        maintain(nex);
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        root=-1,size=0;
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            insert(root,x);
        }
        int tot=n;
        while(m--)
        {
            char op[10];
            int x;
            scanf("%s%d",op,&x);
            if(strcmp(op,"query")==0)printf("%d\n",ask(tot-x+1));
            else if(strcmp(op,"insert")==0)insert(root,x),tot++;
            else if(strcmp(op,"delete")==0)Delete(x),tot--;
        }
        //show(root);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值