zoukankan      html  css  js  c++  java
  • bzoj 3600 没有人的算术——二叉查找树动态标号

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3600

    已知 l 和 r 的排名,想快速知道 k 的排名。那么建一个 BIT ,用已知的排名做比较,走到一个位置,就知道自己的排名了。

    但这样会让很多点的排名改变。如果用实数表示标号就可以方便地生成一个 “两个排名之间的排名” 而不影响其他点。

     BIT 的每个节点代表一个曾经出现过的序列里的点,有自己的实数标号和 ( l , r ) 的组成。

    如果把实数标号不是记在 BIT 节点上而是记在序列上,即 v[ i ] 表示序列第 i 个位置的标号,那么修改 k 位置的话,其他曾经调用 k 而组成的点也会收到影响。

    所以实数标号记在 BIT 节点上,序列记一个 dy[ ] 表示它对应 BIT 哪个点。序列一个位置的 ( l , r ) 记录成 BIT 上对应的点即可。

    用替罪羊树实现平衡。那么在重构的时候要注意,因为 dy[ ] 不会改变,所以 BIT 上点标之间的大小关系也不应改变。只要在回收的时候不是回收 Node 而是回收 int 即可(int 是那个 Node 的角标)。

    最开始的时候只有一个 0 。那么 BIT 里唯一的节点表示 “只有一个 0 ” ,其 l 就是自己, r 是 0 (BIT 节点从1标号)。v[ 1 ] 会是 0.5 (如果标号总范围是 ( 0 , 1 ) 的话), v[ 0 ] 会是 0 ,这样就表示了 “没有” 是最小的。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define db double
    #define ls Ls[cr]
    #define rs Rs[cr]
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=1e5+5,M=5e5+5;
    const db sl=0.75;
    int n,rt,tot,c0[M],c1[M],siz[M],dy[N]; db v[M];
    int Ls[N<<1],Rs[N<<1],mx[N<<1];
    int rcr,rfa,sta[M],top; bool rfx; db rL,rR;
    struct Node{
      int l,r;
      Node(int l=0,int r=0):l(l),r(r) {}
      bool operator< (const Node &b)const
      { return v[l]==v[b.l]?v[r]<v[b.r]:v[l]<v[b.l];}
      bool operator== (const Node &b)const
      { return v[l]==v[b.l]&&v[r]==v[b.r];}
    }a[M];
    int Mx(int u,int v){return u>v?u:v;}
    Node Mx(Node u,Node v){return u<v?v:u;}
    void build(int l,int r,int cr)
    {
      mx[cr]=l; if(l==r)return;
      int mid=l+r>>1;
      ls=++tot; build(l,mid,ls);
      rs=++tot; build(mid+1,r,rs);
    }
    void mdfy(int l,int r,int cr,int p)
    {
      if(l==r)return; int mid=l+r>>1;
      if(p<=mid)mdfy(l,mid,ls,p);
      else mdfy(mid+1,r,rs,p);
      if(a[dy[mx[ls]]]<a[dy[mx[rs]]])mx[cr]=mx[rs];
      else mx[cr]=mx[ls];
    }
    int qry(int l,int r,int cr,int L,int R)
    {
      if(l>=L&&r<=R)return mx[cr];
      int mid=l+r>>1;
      if(R<=mid)return qry(l,mid,ls,L,R);
      if(mid<L)return qry(mid+1,r,rs,L,R);
      int u=qry(l,mid,ls,L,R), v=qry(mid+1,r,rs,L,R);
      if(a[dy[u]]<a[dy[v]])return v;
      else return u;
    }
    void chk(int cr,db L,db Md,db R)
    {
      if(Mx(siz[c0[cr]],siz[c1[cr]])>=siz[cr]*sl)rcr=cr;
      if(rcr==c0[cr])
        { rfa=cr; rfx=0; rL=L; rR=Md;}
      if(rcr==c1[cr])
        { rfa=cr; rfx=1; rL=Md; rR=R;}
    }
    int ins(int &cr,Node k,db L,db R)
    {
      db Md=(L+R)/2;
      if(!cr)
        {
          cr=++tot; a[cr]=k;
          v[cr]=Md;siz[cr]=1;return cr;
        }
      if(k==a[cr])return cr;
      int ret=0; siz[cr]++;
      if(k<a[cr])ret=ins(c0[cr],k,L,Md);
      else ret=ins(c1[cr],k,Md,R);
      chk(cr,L,Md,R); return ret;
    }
    void del_dfs(int cr)//sorted!!
    {
      if(c0[cr])del_dfs(c0[cr]);
      sta[++top]=cr;
      if(c1[cr])del_dfs(c1[cr]);
    }
    void bld(int l,int r,int &cr,db L,db R)
    {
      db Md=(L+R)/2; int mid=l+r>>1;
      cr=sta[mid];
      c0[cr]=c1[cr]=0; siz[cr]=1; v[cr]=Md;
      if(l<mid)bld(l,mid-1,c0[cr],L,Md);
      if(mid<r)bld(mid+1,r,c1[cr],Md,R);
      siz[cr]=siz[c0[cr]]+siz[c1[cr]]+1;
    }
    void rebld(int &cr,db L,db R)
    {
      top=0; del_dfs(cr); bld(1,top,cr,L,R);
    }
    int main()
    {
      n=rdn();int m=rdn(); char ch[5];
      tot=1;build(1,n,1);
      tot=0; ins(rt,Node(1,0),0,1);//v[1]=0.5//v[0]=0 is min
      for(int i=1;i<=n;i++)dy[i]=1;
      for(int i=1,l,r,k;i<=m;i++)
        {
          scanf("%s",ch); l=rdn();r=rdn();
          if(ch[0]=='C')
        {
          k=rdn();
          dy[k]=ins(rt,Node(dy[l],dy[r]),0,1);
          Node tp=a[dy[k]];
          mdfy(1,n,1,k);
          if(rcr)
            {
              if(rcr==rt)rebld(rt,0,1);
              else if(!rfx)rebld(c0[rfa],rL,rR);
              else rebld(c1[rfa],rL,rR);
              rcr=0;
            }
        }
          else printf("%d
    ",qry(1,n,1,l,r));
        }
      return 0;
    }
  • 相关阅读:
    ContentProvider总结2
    ContentProvider总结
    ContentObserver的使用完整详细示例
    性能优化之Java(Android)代码优化
    联系人数据库contacts2.db介绍
    contact2.db最强详解
    Android Uri、UriMatcher、ContentUris详解
    Android三种ContentResolver查询方式
    Oracle SQL_杂记
    啥是Restful?
  • 原文地址:https://www.cnblogs.com/Narh/p/10698529.html
Copyright © 2011-2022 走看看