数列[专杀Splay版]

时间限制: 3 Sec  内存限制: 128 MB
提交: 49  解决: 7

题目描述

输入一个数列,你需要进行如下操作: 
1、 把编号为I的数值改为K 
2、 输出从小到大排序后第k个数

输入

输入文件第一行包含两个整数N、M,分别表示数列长度与操作个数。 
第二行有N个整数,为初始数列中的N个整数。 
接下来M行每行如果只有一个整数k,那么就是输出第k小数,否则两个整数I,K表示把第I个数的数值改为K。

输出

输出所有要求输出的数,每个数单独一行。

样例输入

5 3
5 3 2 1 1
4
2 6
4

样例输出

3
5

提示

N,M≤200,000

数列中所有数字的绝对值不大于100,000,000
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<ctime>
using namespace std;
const int maxn=200001;
int n,m;
struct node
{
    int key,rev,size;
    node *child[2],*father;
}bst[maxn],*root;
node *pos=bst;
queue<node*>mem;
void update(node* &r)
{
    if(r)
    r->size=(r->child[0]!=NULL?r->child[0]->size:0)+(r->child[1]!=NULL?r->child[1]->size:0)+1;
}
void rotate(node* &r,int b)
{
    node *y=r->child[!b];
    r->child[!b]=y->child[b];
    y->child[b]=r;
    update(r);
    r=y;
    update(r);
}
void newnode(node* &r,int key)
{
    if(mem.empty())r=pos++;
    else r=mem.front(),mem.pop();
    r->key=key;
    r->size=0;
    r->rev=rand();
    r->child[1]=r->child[0]=NULL;
}
void insert(node* &r,int key)
{
    if(!r)newnode(r,key);
    else
    {
        bool b=r->key<key;
        insert(r->child[b],key);
        if(r->child[b]->rev<r->rev)
            rotate(r,!b);
    }
    update(r);
}
void delet(node* &r,int key)
{
    if(!r)return;
    if(r->key==key)
    {
        if(r->child[1]&&r->child[0])
        {
            bool b=r->child[0]->rev<r->child[1]->rev;
            rotate(r,b);
            delet(r->child[b],key);
        }
        else
        {
            mem.push(r);
            if(r->child[0])r=r->child[0];
            else r=r->child[1];
        }
    }
    else
    {
        bool b=r->key<key;
        delet(r->child[b],key);
    }
    update(r);
}
int end,len;
int read(char s[],int begin)
{
    int i,ans=0,f=1;
    for(i=begin;i<len;i++)
    {
        if(s[i]>='0'&&s[i]<='9')  ans=ans*10+s[i]-'0';
        else if(s[i]=='-')f=-1;
        else break;
    }
    if(begin==i)return 2000000000;
    end=i+1;
    return ans*f;
}
int find(node* &r,int x)
{
    if(r==NULL)return 2000000000;
    if(r->child[0]!=NULL&&x==r->child[0]->size)return r->key;
    if(!x&&r->child[0]==NULL)return r->key;
    if(!x)return find(r->child[0],x);
    if(r->child[0]!=NULL&&r->child[1]!=NULL)
    {
        int t=r->child[0]->size;
        if(t>x)return find(r->child[0],x);
        else if(t<x)return find(r->child[1],x-t-1);
    }
    else
    {
        if(r->child[0]==NULL)return find(r->child[1],x-1);
        if(r->child[1]==NULL)return find(r->child[0],x);
    }
    return 2000000000;
}
int a[maxn];
int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&j);
        a[i]=j;
        insert(root,j);
    }
    char s[101];
    getchar();
    for(i=1;i<=m;i++)
    {
        len=0;
        while(len==0)gets(s),len=strlen(s);
        int x=read(s,0),y=read(s,end);
        if(y!=2000000000)
        {
            delet(root,a[x]);
            a[x]=y;
            insert(root,a[x]);
        }
        else
        {
            int ans=find(root,x-1);
            if(ans!=2000000000)
            printf("%d
",ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/huangdalaofighting/p/6788776.html