(题面都一样,就不贴了)
今天讲了分块,于是就用分块写了一下这道平衡树模板题hh
离散化之后按权值分块即可,跑得竟然比我平衡树的代码还快hhh
/************************************************************** Problem: 3224 User: JYYHH Language: C++ Result: Accepted Time:320 ms Memory:3268 kb ****************************************************************/ #include<bits/stdc++.h> #define ll long long #define maxn 100005 using namespace std; int n,num[maxn]; int sz,bl[maxn],c[maxn]; int tot[1005],lef[1005],rig[1005]; int opt[maxn],b[maxn],ky,ans,blnum; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",opt+i,b+i); if(opt[i]!=4) num[++ky]=b[i]; } sort(num+1,num+ky+1); ky=unique(num+1,num+ky+1)-num-1; for(int i=1;i<=n;i++) if(opt[i]!=4) b[i]=lower_bound(num+1,num+ky+1,b[i])-num; sz=sqrt(ky); for(int i=1;i<=ky;i++) bl[i]=(i-1)/sz+1; blnum=(ky-1)/sz+1; for(int i=1;i<=n;i++){ if(opt[i]==1){ int to=bl[b[i]]; c[b[i]]++,tot[to]++; if(c[b[i]]==1){ if(!lef[to]||b[i]<lef[to]) lef[to]=b[i]; if(!rig[to]||b[i]>rig[to]) rig[to]=b[i]; } } else if(opt[i]==2){ int to=bl[b[i]]; c[b[i]]--,tot[to]--; if(!tot[to]) lef[to]=rig[to]=0; else if(!c[b[i]]){ if(b[i]==lef[to]){ for(int j=b[i];bl[j]==to;j++) if(c[j]){ lef[to]=j; break; } } if(b[i]==rig[to]){ for(int j=b[i];bl[j]==to;j--) if(c[j]){ rig[to]=j; break; } } } } else if(opt[i]==3){ ans=0; int to=bl[b[i]]; for(int j=b[i]-1;bl[j]==to;j--) ans+=c[j]; for(int j=to-1;j>0;j--) ans+=tot[j]; printf("%d ",ans+1); } else if(opt[i]==4){ int tt=0,pos; for(int j=1;j<=blnum;j++){ tt+=tot[j]; if(tt>=b[i]){ tt-=tot[j],pos=j; break; } } for(int j=lef[pos];bl[j]==pos;j++){ tt+=c[j]; if(tt>=b[i]){ printf("%d ",num[j]); break; } } } else if(opt[i]==5){ int to=bl[b[i]],j; for(j=b[i]-1;bl[j]==to;j--) if(c[j]){ printf("%d ",num[j]); break; } if(bl[j]!=to){ for(int j=to-1;j>0;j--) if(rig[j]){ printf("%d ",num[rig[j]]); break; } } } else{ int to=bl[b[i]],j; for(j=b[i]+1;bl[j]==to;j++) if(c[j]){ printf("%d ",num[j]); break; } if(bl[j]!=to){ for(int j=to+1;j<=blnum;j++) if(lef[j]){ printf("%d ",num[lef[j]]); break; } } } } return 0; }