BZOJ2770: YY的Treap
原本看标题还以为是treap的题,但是实际上是线段树。
求两点的LCA相当于求区间priority最小值的位置。
然后就可以离线先离散化然后建树做了。
记录的minpos是线段树上叶子结点的节点编号。
一道水题。
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<set> using namespace std; const long long maxn=1e5+10,maxm=3e5+10,INF=1e18; long long n,m; long long pp[maxn],pr[maxn],rr[maxm],rp[maxm]; char kk[maxm]; long long num[maxn+maxm],tot=0; set<long long> G; set<long long>::iterator it; long long aa,ff;char cc; long long read() { aa=0;ff=1;cc=getchar(); while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa*ff; } struct Node{ int l,r,minpos;long long minnum; }node[4*(maxn+maxm)]; void bld(int pos,int l,int r) { node[pos].l=l;node[pos].r=r; node[pos].minnum=INF; if(l==r) { node[pos].minpos=pos; return; } int mid=(l+r)>>1; bld(pos<<1,l,mid); bld(pos<<1|1,mid+1,r); node[pos].minpos=node[pos<<1].minpos; } void chge(int pos,int os,long long prr) { if(node[pos].l==node[pos].r) { node[pos].minnum=prr; node[pos].minpos=pos; return ; } int mid=(node[pos].l+node[pos].r)>>1; if(os<=mid) chge(pos<<1,os,prr); else chge(pos<<1|1,os,prr); node[pos].minnum=min(node[pos<<1].minnum,node[pos<<1|1].minnum); node[pos].minpos= node[pos<<1].minnum<node[pos<<1|1].minnum? node[pos<<1].minpos:node[pos<<1|1].minpos; } int ef(int l,int r,long long key) { if(l>=r-1) return l; int mid=(l+r)>>1; if(num[mid]==key) return mid; if(num[mid]>key) return ef(l,mid,key); return ef(mid+1,r,key); } int q(int pos,int l,int r) { if(l>r) swap(l,r); if(node[pos].l==l&&node[pos].r==r) return node[pos].minpos; int mid=(node[pos].l+node[pos].r)>>1; if(l>mid) return q(pos<<1|1,l,r); if(r<=mid) return q(pos<<1,l,r); int ans1=q(pos<<1,l,mid),ans2=q(pos<<1|1,mid+1,r); return node[ans1].minnum<node[ans2].minnum? ans1:ans2; } int main() { n=read();m=read(); for(int i=1;i<=n;++i) { pp[i]=read(); G.insert(pp[i]); } for(int i=1;i<=n;++i) pr[i]=read(); for(int i=1;i<=m;++i) { kk[i]=getchar(); while(kk[i]<'A'||kk[i]>'Z') kk[i]=getchar(); rr[i]=read(); if(kk[i]!='D') rp[i]=read(); if(kk[i]=='I') G.insert(rr[i]); } for(it=G.begin();it!=G.end();++it) num[++tot]=*it; bld(1,1,tot); for(int i=1;i<=n;++i) chge(1,ef(1,tot+1,pp[i]),pr[i]); for(int i=1;i<=m;++i) { if(kk[i]=='I') chge(1,ef(1,tot+1,rr[i]),rp[i]); else if(kk[i]=='D') chge(1,ef(1,tot+1,rr[i]),INF); else printf("%lld\n",num[node[q(1,ef(1,tot+1,rr[i]),ef(1,tot+1,rp[i]))].l]); } return 0; }
弱者就是会被欺负呀