• 替罪羊树模板(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
    ",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("
    ");
            }
          }
      }
  • 相关阅读:
    前端程序员应该知道的 15 个 jQuery 小技巧
    UML 序列图详解
    UML实践详细经典教程----用例图、顺序图、状态图、类图、包图、协作图
    浅谈UML的概念和模型之UML九种图
    [TFS教程]TFS: Get Command
    cmd下PUSHD和POPD命令使用说明
    IIS 7.0的集成模式和经典模式
    sql日期格式化
    VS2010自定义添加创建者、创建时间等个人信息新建文件模版
    瞎打一波
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/5610675.html
Copyright © 2020-2023  润新知