提交: 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; }