题意:
给你个序列和一串询问 询问前a[i]个数字第i小的是几
思路:
动态的第k值问题 由于区间只增不减所以是水题
利用平衡树解决这类问题
treap是方便编写的类似平衡树的产品
treap方便实现BST的功能 splay更适合于去维护区间
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<ctime> #include<cstdlib> using namespace std; #define N 30010 #define inf ((1U<<31)-1) #define L(x) (ch[x][0]) #define R(x) (ch[x][1]) int ch[N][2],val[N],priority[N],num[N],size[N]; int tot,root; int newnode(int &u,int w) { u=++tot; L(u)=R(u)=0; priority[u]=rand(); num[u]=size[u]=1; val[u]=w; return u; } inline void up(int u) { size[u]=size[L(u)]+size[R(u)]+num[u]; } void rotate(int &u,int kind) { int y=ch[u][kind^1]; ch[u][kind^1]=ch[y][kind]; ch[y][kind]=u; up(u); up(y); u=y; } int insert(int &u,int w) { if(!u) return newnode(u,w); int res,kind; if(w==val[u]) { num[u]++; res=u; } else { kind=(w>val[u]); res=insert(ch[u][kind],w); if(priority[ch[u][kind]]<priority[u]) rotate(u,kind^1); } up(u); return res; } int select(int u,int k) { if(size[L(u)]>=k) return select(L(u),k); if(size[L(u)]+num[u]>=k) return val[u]; return select(R(u),k-size[L(u)]-num[u]); } void remove(int &u,int w) { if(val[u]==w) { if(num[u]>1) num[u]--; else if(!L(u)&&!R(u)) { u=0; return ; } else { int kind=(priority[L(u)]<priority[R(u)]); rotate(u,kind); remove(u,w); } } else remove(ch[u][w>val[u]],w); up(u); } void init() { R(0)=L(0)=size[0]=num[0]=val[0]=0; priority[0]=inf; tot=root=0; newnode(root,inf); } int n,m; int a[N],b[N]; int main() { int i,j; while(~scanf("%d%d",&n,&m)) { srand(n*5-m+19930909); init(); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(j=1;j<=m;j++) scanf("%d",&b[j]); for(j=1,i=1;j<=m;j++) { while(i<=b[j]) { insert(root,a[i]); i++; } printf("%d\n",select(root,j)); } } return 0; }
原文地址:http://blog.csdn.net/houserabbit/article/details/38071187