• 题解 P3871 【[TJOI2010]中位数】


    orz各位大佬,题解太强了,主席树,堆,线段树,splay,还有暴力,太巨了。所以我用的是fhq treap(好像更高级)。算了。

    反正都是平衡树,这道题就是动态求中位数,不会做的同学可以先做弱化版P1168

    至于不会fhq treap的同学可以先点这里或上 Patrickpwq大佬的博客

    fhq treap做这道题涉及到insert(插入)与find(求第k小的数),至于k,就随add增大就好了,所以说fhq treap太好用了。

    insert的原理就不说了,至于find的原理我就简单讲一下,fhq treap是用treap来存,treap就是堆与树的合并,所以我们叫它二叉搜索树,所以它具有堆的性质,所以就搜右子树大小。(详细可以戳上面)

    嗯,上代码。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<ctime>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<algorithm>
      7 #define maxn 200010
      8 using namespace std;
      9 int n,val[maxn],rnd[maxn],son[maxn][3],size[maxn],sum_p,m;
     10 //val存权值,rnd存rand出的值,son存左右儿子,size存大小。
     11 inline void read(int &x)
     12 {
     13     x=0;int f=1; 
     14     char ch=getchar();
     15     while(ch<'0'||ch>'9')
     16     {if(ch=='-') f=-1; ch=getchar();}
     17     while(ch>='0'&&ch<='9')
     18     {x=x*10+ch-'0';ch=getchar();}
     19     x*=f;
     20 }
     21 inline int newnode(int x)
     22 {
     23     ++sum_p;size[sum_p]=1;
     24     val[sum_p]=x;rnd[sum_p]=rand();
     25     return sum_p; 
     26 }
     27 inline void update(int x)
     28 {
     29     size[x]=size[son[x][1]]+size[son[x][2]]+1;
     30 }
     31 inline void split(int &x,int &y,int k,int pos)//拆树
     32 {
     33     if(!pos)x=y=0;
     34     else
     35     {
     36         if(val[pos]<=k)//(拆成比k大与不大于k)
     37         {x=pos;split(son[pos][2],y,k,son[pos][2]);}
     38         else
     39         {y=pos;split(x,son[pos][1],k,son[pos][1]);}
     40         update(pos);
     41     }
     42 }
     43 inline int merge(int x,int y)//合并
     44 {
     45     if(x==0||y==0) return x+y;
     46     if(rnd[x]<rnd[y])//如果rand[x]<rand[y] 我们就把y接在x的右儿子上
     47     {
     48         son[x][2]=merge(son[x][2],y);
     49         update(x);return x;
     50     }
     51     else//反之同理
     52     {
     53         son[y][1]=merge(x,son[y][1]);
     54         update(y);return y;
     55     }
     56 }
     57 inline int find(int pos,int rank)
     58 {
     59     while(1)//(原理上面已讲)
     60     {
     61         if(size[son[pos][1]]>=rank)
     62         {
     63             pos=son[pos][1];
     64         }
     65         else 
     66         if(size[son[pos][1]]+1==rank)return pos;
     67         else
     68         {
     69             rank-=size[son[pos][1]]+1;
     70             pos=son[pos][2];
     71         }
     72     }
     73 }
     74 int main()
     75 {
     76     srand((unsigned)time(NULL));
     77     int b,x,y,z,op,root=0,m;
     78     read(n);
     79     for(register int i=1;i<=n;i++)
     80     {
     81         read(op);
     82         split(x,y,op,root);//拆开
     83         root=merge(merge(x,newnode(op)),y);//插入,合并回来
     84     }
     85     read(m);char a[3]; 
     86     for(register int i=1;i<=m;i++)
     87     {
     88         scanf("%s%d",a,&b);
     89         if(a[0]=='a')
     90         {
     91             split(x,y,b,root);
     92             root=merge(merge(x,newnode(b)),y);
     93             n++;//中位数是动态的,所以改变总个数就好了。
     94         }
     95         else
     96         {
     97             register int mid=(n+1)/2;//加1的原因就不说了
     98             printf("%d
    ",val[find(root,mid)]);
     99         }
    100     }
    101 }
  • 相关阅读:
    希尔排序(java实现)
    直接插入排序(java实现)
    android AsyncTask使用限制
    android TranslateAnimation动画执行时的坐标获取。
    android内存管理机制
    android实现前置后置摄像头相互切换
    【转-整理】JavaWeb框架中,各层的解释和关系
    安卓系统上安装.net运行时 mono runtime
    你不知道的https工作原理
    HTTPS的误解(二)
  • 原文地址:https://www.cnblogs.com/mashiro-/p/9526438.html
Copyright © 2020-2023  润新知