1 条题解
-
0
自动搬运
来自洛谷,原作者为

陈曦
**搬运于
2025-08-24 21:53:36,当前版本为作者最后更新于2018-08-01 21:34:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
orz各位大佬,题解太强了,主席树,堆,线段树,splay,还有暴力,太巨了。所以我用的是fhq treap(
好像更高级)。算了。反正都是平衡树,这道题就是动态求中位数,不会做的同学可以先做弱化版P1168
至于不会fhq treap的同学可以先点这里或者这里(
记得点赞)fhq treap做这道题涉及到insert(插入)与find(求第k小的数),至于k,就随add增大就好了,所以说fhq treap太好用了。
insert的原理就不说了,至于find的原理我就简单讲一下,fhq treap是用treap来存,treap就是堆与树的合并,所以我们叫它二叉搜索树,所以它具有堆的性质,所以就搜右子树大小。(详细可以戳上面)
嗯,上代码。
#include<iostream> #include<cstdio> #include<ctime> #include<cstdlib> #include<cstring> #include<algorithm> #define maxn 200010 using namespace std; int n,val[maxn],rnd[maxn],son[maxn][3],size[maxn],sum_p,m; //val存权值,rnd存rand出的值,son存左右儿子,size存大小。 inline void read(int &x) { x=0;int f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} x*=f; } inline int newnode(int x) { ++sum_p;size[sum_p]=1; val[sum_p]=x;rnd[sum_p]=rand(); return sum_p; } inline void update(int x) { size[x]=size[son[x][1]]+size[son[x][2]]+1; } inline void split(int &x,int &y,int k,int pos)//拆树 { if(!pos)x=y=0; else { if(val[pos]<=k)//(拆成比k大与不大于k) {x=pos;split(son[pos][2],y,k,son[pos][2]);} else {y=pos;split(x,son[pos][1],k,son[pos][1]);} update(pos); } } inline int merge(int x,int y)//合并 { if(x==0||y==0) return x+y; if(rnd[x]<rnd[y])//如果rand[x]<rand[y] 我们就把y接在x的右儿子上 { son[x][2]=merge(son[x][2],y); update(x);return x; } else//反之同理 { son[y][1]=merge(x,son[y][1]); update(y);return y; } } inline int find(int pos,int rank) { while(1)//(原理上面已讲) { if(size[son[pos][1]]>=rank) { pos=son[pos][1]; } else if(size[son[pos][1]]+1==rank)return pos; else { rank-=size[son[pos][1]]+1; pos=son[pos][2]; } } } int main() { srand((unsigned)time(NULL)); int b,x,y,z,op,root=0,m; read(n); for(register int i=1;i<=n;i++) { read(op); split(x,y,op,root);//拆开 root=merge(merge(x,newnode(op)),y);//插入,合并回来 } read(m);char a[3]; for(register int i=1;i<=m;i++) { scanf("%s%d",a,&b); if(a[0]=='a') { split(x,y,b,root); root=merge(merge(x,newnode(b)),y); n++;//中位数是动态的,所以改变总个数就好了。 } else { register int mid=(n+1)/2;//加1的原因就不说了 printf("%d\n",val[find(root,mid)]); } } }如果各位大佬觉得讲的还行,请赏一个赞,谢谢。
- 1
信息
- ID
- 2828
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者