zoukankan      html  css  js  c++  java
  • 题解 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 }
  • 相关阅读:
    BZOJ 1191 HNOI2006 超级英雄hero
    BZOJ 2442 Usaco2011 Open 修建草坪
    BZOJ 1812 IOI 2005 riv
    OJ 1159 holiday
    BZOJ 1491 NOI 2007 社交网络
    NOIP2014 D1 T3
    BZOJ 2423 HAOI 2010 最长公共子序列
    LCA模板
    NOIP 2015 D1T2信息传递
    数据结构
  • 原文地址:https://www.cnblogs.com/mashiro-/p/9526438.html
Copyright © 2011-2022 走看看