替罪羊树模板(BZOJ1056/1862)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#define LL long long 
#define LDB long double
using namespace std;

  LDB alpha=0.75;
  const LL mo=3000001;
  int newadd;
  int root=1,datcnt,rbcnt,cnt,nodeintree,delnode;
  char ans[20];
  int nd[3000001],nex[3000001];
  int rb[600001];
  LL key[3000001];
 
  struct treenode{
      int size,lc,rc,num,fa,tim,v,dep;
      LL nam;
      
      inline bool operator < (const treenode&a) const {
          if (num<a.num) return(1);
          if (num>a.num) return(0);
          if (tim>a.tim) return(1);
          return(0);
      }
      
    inline bool operator == (const treenode&a) const{
       if ((a.num==num)&&(a.tim==tim)&&(a.nam==nam)) return(1);
       return(0);
    }  
  }tr[600001],dat[600001];
  
  LL namhash(char* st){
      LL t=0,len=strlen(st);
      for (int i=1;i<len;i++) 
      t*=27,t+=st[i]-'A'+1;
      return(t);
  }
  
  int numget(char* st){
      int t=0,len=strlen(st);
      for (int i=1;i<len;i++) t*=10,t+=st[i]-'0';
      return(t);
  }
  
  void namtrans(LL nam){
    int cnt=-1;LL t=1;
    while (t<=nam)
     t*=27,cnt+=1;
      
      for (int i=cnt;i>=0;i--) ans[i]=nam%27+'A'-1,nam/=27;
      for (int i=0;i<=cnt;i++) putchar(ans[i]);
  }
  
  int hash_query(LL nam){
      int po=nam%mo;
      for (int p=nd[po];p!=-1;p=nex[p])
        if (key[p]==nam) return(p);
      nex[++datcnt]=nd[po];nd[po]=datcnt;key[datcnt]=nam;
      newadd=1;
      return(datcnt);  
  }
  
  int getrank(int po,treenode t){
      if ((t==tr[po])&&(tr[po].v!=0)) return(tr[tr[po].lc].size+tr[po].v);
      if (t<tr[po]) return(getrank(tr[po].lc,t));
      if (tr[po]<t) return(getrank(tr[po].rc,t)+tr[tr[po].lc].size+tr[po].v);
  }
  
  LL getkth(int po,int num){
      if (num<=tr[tr[po].lc].size) return(getkth(tr[po].lc,num));
      if (num>tr[tr[po].lc].size+tr[po].v) return(getkth(tr[po].rc,num-tr[tr[po].lc].size-tr[po].v));
      return(tr[po].nam);
  }
  
  void dfs(int po){
      if (tr[po].lc) dfs(tr[po].lc);
      if (tr[po].v) rb[++rbcnt]=po;else nodeintree--,delnode--;
      if (tr[po].rc) dfs(tr[po].rc);
  }
  
  void build(int l,int r){
      int mid=(l+r)>>1,po=rb[(l+r)/2];
      
      if (l<mid){
      tr[po].lc=rb[(l+mid-1)/2];
      tr[rb[(l+mid-1)/2]].fa=po;
      tr[rb[(l+mid-1)/2]].dep=tr[po].dep+1;
      build(l,mid-1);
      }else tr[po].lc=0;
      if (r>mid){
      tr[po].rc=rb[(r+mid+1)/2];
      tr[rb[(r+mid+1)/2]].fa=po;
      tr[rb[(r+mid+1)/2]].dep=tr[po].dep+1;
      build(mid+1,r);
      }else tr[po].rc=0;
      tr[po].size=tr[tr[po].lc].size+tr[tr[po].rc].size+tr[po].v;
  }
  
  void rebuild(int po){
      rbcnt=0;dfs(po);
      
      if (po!=root){
          tr[rb[(rbcnt+1)/2]].fa=tr[po].fa;
          tr[rb[(rbcnt+1)/2]].dep=tr[tr[po].fa].dep+1;
          if (po==tr[tr[po].fa].lc) tr[tr[po].fa].lc=rb[(rbcnt+1)/2];
          else tr[tr[po].fa].rc=rb[(rbcnt+1)/2];
    }else {root=rb[(rbcnt+1)/2];tr[rb[(rbcnt+1)/2]].fa=0;tr[rb[(rbcnt+1)/2]].dep=0;}
    
    build(1,rbcnt);
  }
  
  void scapegoat_insert(int num){
      nodeintree++;
      if ((tr[root].size==0)&&(tr[root].lc==0)&&(tr[root].rc==0)) {
          root=++cnt;tr[root]=dat[num];tr[root].dep=0;
          tr[cnt].v=1;tr[cnt].size=1;
          return;
      }
    int po=root;
    while (1){
        tr[po].size++;
        
        if (dat[num]==tr[po]) {tr[po].v++;break;}
        
        if (dat[num]<tr[po]){
            if (tr[po].lc==0){
                tr[++cnt]=dat[num];
                tr[cnt].fa=po;
                tr[po].lc=cnt;
                tr[cnt].dep=tr[po].dep+1;
                tr[cnt].v=1;tr[cnt].size=1;
                break;
            }else {po=tr[po].lc;continue;}
        }
            
        if (tr[po]<dat[num]){
            if (tr[po].rc==0){
                tr[++cnt]=dat[num];
                tr[cnt].fa=po;
                tr[po].rc=cnt;
                tr[cnt].dep=tr[po].dep+1;
                tr[cnt].v=1;tr[cnt].size=1;
                break;
            }else {po=tr[po].rc;continue;}
        }    
    }  
        
    if (tr[po].dep>(log(tr[root].size)/log(1/alpha))){
        int dp=tr[po].dep;
        while ((dp-tr[po].dep)<=(log(tr[po].size)/log(1/alpha))) po=tr[po].fa;
        rebuild(po);
    }    
  }
  
  void scapegoat_delete(int num){
      int po=root;
      while (1){
        tr[po].size--;    
        if (tr[po]<dat[num]) {po=tr[po].rc;continue;}
      if (dat[num]<tr[po]) {po=tr[po].lc;continue;}
      if (tr[po]==dat[num]) {tr[po].v--;if (tr[po].v==0) delnode++;break;}        
    }
    if (delnode>nodeintree/2) rebuild(root);
  }

  int main(){
      
      freopen("a.in","r",stdin);
      
      int n;char st[20];
      scanf("%d",&n);
      
      for (int i=0;i<=3000000;i++) nd[i]=-1;
      
      for (int i=1;i<=n;i++){
          scanf("%s",st);
          
          if (st[0]=='+'){
              LL nam=namhash(st);
              newadd=0;
              int po=hash_query(nam);
              if (!newadd) {    
                scapegoat_delete(po);
                dat[po].nam=nam;scanf("%d",&dat[po].num);dat[po].tim=i;
                scapegoat_insert(po);
            }else{
              dat[po].nam=nam;scanf("%d",&dat[po].num);dat[po].tim=i;
              scapegoat_insert(po);    
            }
        }
        
        if ((st[0]=='?')&&(st[1]<='Z')&&(st[1]>='A')){
            LL nam=namhash(st);
            int po=hash_query(nam);
            printf("%d\n",datcnt-getrank(root,dat[po])+1);
        }
        
        if ((st[0]=='?')&&(st[1]<='9')&&(st[1]>='0')){
            int po=numget(st);
            for (int i=po;i<=min(po+9,datcnt);i++) {
                namtrans(getkth(root,datcnt-i+1));
                if (i!=min(po+9,datcnt))printf(" ");
            }
            printf("\n");
        }
      }
  }

 

posted @ 2016-06-23 14:19  z1j1n1  阅读(...)  评论(...编辑  收藏