传送门
解析:
(这句话仅针对指针)事实证明,在需要全局初始化的情况下,静态数组没有动态分配内存快。所以要么动态内存,要么静态内存动态初始化。
可持久化平衡树裸题,没什么好说的,我写的是非旋treap。
非旋treap的分裂关键字用大小考虑就行了。
不过听说这道题卡输入输出,建议加一个优化。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const
namespace IO{
cs int Rlen=1<<18|1;
char buf[Rlen],*p1,*p2;
char obuf[Rlen],*p3=obuf,*p4=obuf+Rlen;
inline char get_char(){
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=num*10+(c^48);
return num;
}
inline void put_char(cs char &c){
*p3++=c;
if(p3==p4)fwrite(obuf,1,Rlen,stdout),p3=obuf;
}
inline void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
inline void FLUSH(){
if(p3==obuf)return ;
fwrite(obuf,1,p3-obuf,stdout);
p3=obuf;
}
}
using namespace IO;
cs int N=300005;
typedef struct treap_node *point;
struct treap_node{
point lc,rc;
int val,siz,pri;
treap_node(int _v=0):lc(NULL),rc(NULL),val(_v),pri(rand()),siz(1){}
inline void pushup(){
siz=(lc?lc->siz:0)+(rc?rc->siz:0)+1;
}
};
inline point newnode(int _v=0){
point p;
p=(point)malloc(sizeof(treap_node));
*p=treap_node(_v);
return p;
}
typedef pair<point,point> data;
data split(point now,cs int &key){
if(!now)return make_pair((point)NULL,(point)NULL);
point p=(point)malloc(sizeof(treap_node));
*p=*now;
data res;
if(key<=(now->lc?now->lc->siz:0)){
res=split(now->lc,key);
p->lc=res.second;
p->pushup();
return make_pair(res.first,p);
}
else{
res=split(now->rc,key-(now->lc?now->lc->siz:0)-1);
p->rc=res.first;
p->pushup();
return make_pair(p,res.second);
}
}
point merge(point a,point b){
if(!a)return b;
if(!b)return a;
point p=(point)malloc(sizeof(treap_node));
if(a->pri>b->pri){
*p=*a;
p->rc=merge(a->rc,b);
}
else{
*p=*b;
p->lc=merge(a,b->lc);
}
p->pushup();
return p;
}
point Insert(point now,cs int &pos,cs int &key){
data res=split(now,pos-1);
point tmp=newnode(key);
return merge(merge(res.first,tmp),res.second);
}
point Delete(point now,cs int &pos){
data res1=split(now,pos-1);
data res2=split(res1.second,1);
free(res2.first);
return merge(res1.first,res2.second);
}
int queryKth(point now,cs int &pos){
if(!now)return 0;
if(pos==(now->lc?now->lc->siz:0)+1)return now->val;
if(pos<=(now->lc?now->lc->siz:0))return queryKth(now->lc,pos);
else return queryKth(now->rc,pos-(now->lc?now->lc->siz:0)-1);
}
point root[N];
int n,tot;
signed main(){
srand(time(0));
n=getint();
while(n--){
int op=getint(),t=getint(),pos=getint(),val;
if(op==1)val=getint();
switch(op){
case 1:{
root[++tot]=Insert(root[t],pos,val);
break;
}
case 2:{
root[++tot]=Delete(root[t],pos);
break;
}
case 3:{
outint(queryKth(root[t],pos));pc('\n');
break;
}
}
}
FLUSH();
return 0;
}