• 【BZOJ 4605】崂山白花蛇草水 替罪羊树套线段树


    外层是借鉴了kd-tree的替罪羊里层是线段树,插入就是正常插入+拍扁重建,查询的时候,我们就像树状数组套线段树一样操作在替罪羊中找到的线段树根节点,但是对于在kd-tree查找过程中遇到的单点,我们并不能将其插入到额外的线段树中,因为你想我们的单点个数是n^1.5级别的,而我们还要乘上一个大到30的logn,就算时间受得了,空间也受不了,就算是回收也可能出事,所以我们就用数组来存单点,查询的时候顺便二分就好了。

    (YY出了一种用链表回收的鬼畜做法....)

    (话说我的空间好像是nlognlogn的.......额.....好像......我不管,我过了)(以后一定要先算内存的啊)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    char xB[(1<<15)+10],*xS,*xT;
    #define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
    inline void read(int &x){
      register char ch=gtc;
      for(x=0;ch<'0'||ch>'9';ch=gtc);
      for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc);
    }
    #define mid ((l+r)>>1)
    #define newnode (node+(sz++))
    #define renode (stack[top--])
    #define diymax(a,b) ((a)>(b)?(a):(b))
    #define diymin(a,b) ((a)<(b)?(a):(b))
    const int N=100010;
    const int oo=1000000000;
    const int Inf=0x3f3f3f3f;
    const double alpha=0.72;
    struct Point{
      int x[2],w;
    }list[N];
    int len,cmp;
    inline bool comp(Point a,Point b){
      return a.x[cmp]<b.x[cmp];
    }
    struct Segment_Tree{
      Segment_Tree *ch[2];
      int size;
      inline void* operator new (size_t);
    }*k1[N*2],*k2[N*2],*C,*mempool,*null,*head;
    int len1,len2;
    int t1[2*N],t2[2*N],cnt1,cnt2;
    inline void* Segment_Tree:: operator new (size_t){
      if(C==mempool){
        C=new Segment_Tree[(1<<16)+10];
        mempool=C+(1<<16)+10;
      }
      return C++;
    }
    inline void Init_Segment_Tree(){
      null=new Segment_Tree;
      null->ch[0]=null->ch[1]=null;
      null->size=0;
    }
    inline void get(Segment_Tree *p){
      p->ch[0]=head,head=p;
    }
    inline Segment_Tree *New(){
      Segment_Tree *ret;
      if(head!=NULL)
        ret=head,head=head->ch[0];
      else
        ret=new Segment_Tree;
      ret->ch[0]=ret->ch[1]=null;
      ret->size=0;
      return ret;
    }
    inline void bang(Segment_Tree *p){
      if(p==null)return;
      bang(p->ch[0]),bang(p->ch[1]);
      get(p);
    }
    inline void insert(Segment_Tree *&p,int l,int r,int key){
      if(p==null)p=New();
      ++p->size;
      if(l==r)return;
      if(key<=mid)insert(p->ch[0],l,mid,key);
      else insert(p->ch[1],mid+1,r,key);
    }
    inline int query(int *x,int z,int y,int jud){
      if(x[z]>jud)return z-1;
      int l=z,r=y,ret=y;
      while(l<=r){
        if(x[mid]<=jud)
          ret=mid,l=mid+1;
        else
          r=mid-1;
      }
      return ret;
    }
    inline int query(int l,int r,int a,int b,int c,int d,int k){
      if(l==r)return l;
      int sum=0,i,mid1=query(t1,a,b,mid),mid2=query(t2,c,d,mid);
      for(i=0;i<len1;++i)sum+=k1[i]->ch[1]->size;
      for(i=0;i<len2;++i)sum-=k2[i]->ch[1]->size;
      sum+=b-mid1,sum-=d-mid2;
      if(sum>=k){
        for(i=0;i<len1;++i)k1[i]=k1[i]->ch[1];
        for(i=0;i<len2;++i)k2[i]=k2[i]->ch[1];
        return query(mid+1,r,mid1+1,b,mid2+1,d,k);
      }else{
        for(i=0;i<len1;++i)k1[i]=k1[i]->ch[0];
        for(i=0;i<len2;++i)k2[i]=k2[i]->ch[0];
        return query(l,mid,a,mid1,c,mid2,k-sum);
      }
    }
    struct ScapeGoat_Tree{
      ScapeGoat_Tree *ch[2];
      Segment_Tree *root;
      int max[2],min[2],size;
      Point poi;
      inline void update(int *x){
        max[0]=diymax(max[0],x[0]);
        max[1]=diymax(max[1],x[1]);
        min[0]=diymin(min[0],x[0]);
        min[1]=diymin(min[1],x[1]);
      }
      inline void pushup(){
        max[0]=diymax(max[0],ch[0]->max[0]);
        max[1]=diymax(max[1],ch[0]->max[1]);
        min[0]=diymin(min[0],ch[0]->min[0]);
        min[1]=diymin(min[1],ch[0]->min[1]);
        max[0]=diymax(max[0],ch[1]->max[0]);
        max[1]=diymax(max[1],ch[1]->max[1]);
        min[0]=diymin(min[0],ch[1]->min[0]);
        min[1]=diymin(min[1],ch[1]->min[1]);
        size=ch[0]->size+ch[1]->size+1;
      }
      inline bool judge(int *x){
        return x[0]>=poi.x[0]&&x[1]>=poi.x[1];
      }
      inline bool judge_max(int *x){
        return x[0]>=max[0]&&x[1]>=max[1];
      }
      inline bool judge_min(int *x){
        return x[0]>=min[0]&&x[1]>=min[1];
      }
      inline bool isbad(){
        return size*alpha+10<ch[0]->size||size*alpha+10<ch[1]->size;
      }
    }*root,*Null,node[N],*stack[N];
    int sz,top;
    inline void New(ScapeGoat_Tree *p,Point poi){
      p->size=1,p->poi=poi;
      p->root=null;
      p->max[0]=p->min[0]=poi.x[0];
      p->max[1]=p->min[1]=poi.x[1];
      p->ch[0]=p->ch[1]=Null;
      insert(p->root,1,oo,poi.w);
    }
    inline void Init_ScapeGoat_Tree(){
      Null=newnode;
      Null->ch[0]=Null->ch[1]=Null;
      Null->root=null;
      Null->max[0]=Null->max[1]=-Inf;
      Null->min[0]=Null->min[1]=Inf;
      Null->size=0;
      root=Null;
    }
    inline void travel(ScapeGoat_Tree *p){
      if(p==Null)return;
      travel(p->ch[0]),travel(p->ch[1]);
      list[++len]=p->poi,stack[++top]=p,bang(p->root);
    }
    inline void build(ScapeGoat_Tree *&p,int l,int r,int id){
      if(l>r)return void(p=Null);
      cmp=id,std::nth_element(list+l,list+mid,list+r+1,comp);
      New(p=renode,list[mid]);
      for(int i=l;i<=r;++i)
        if(i!=mid)insert(p->root,1,oo,list[i].w);
      build(p->ch[0],l,mid-1,id^1);
      build(p->ch[1],mid+1,r,id^1);
      p->pushup();
    }
    inline void rebuild(ScapeGoat_Tree *&p,int id){
      len=0,top=0,travel(p),build(p,1,len,id);
    } 
    inline void insert(ScapeGoat_Tree *&p,Point poi,int id,ScapeGoat_Tree *&ret1,int &ret2){
      if(p==Null)return void(New(p=newnode,poi));
      p->update(poi.x),insert(p->root,1,oo,poi.w),++p->size;
      insert(p->ch[poi.x[id]>p->poi.x[id]],poi,id^1,ret1,ret2);
      if(p->isbad())ret1=p,ret2=id;
    }
    inline void Insert(Point poi){
      ScapeGoat_Tree *p=Null;int id=0;
      insert(root,poi,0,p,id);
      if(p!=Null)rebuild(p,id);
    }
    inline void dfs(ScapeGoat_Tree *p,int *x,Segment_Tree **k,int &t,int *y,int &cc){
      if(p==Null)return;
      if(p->judge_max(x))return void(k[t++]=p->root);
      if(!p->judge_min(x))return;
      if(p->judge(x))y[++cc]=p->poi.w;
      dfs(p->ch[0],x,k,t,y,cc),dfs(p->ch[1],x,k,t,y,cc);
    }
    int main(){
      Init_Segment_Tree();
      Init_ScapeGoat_Tree();
      int T,x,y,a,b,k,f[2],ans=0,opt,cnt,i,clc=0;
      Point temp;
      read(x),read(T);
      while(T--){
        read(opt);
        if(opt==1){
          read(x),read(y),read(a);
          x^=ans,y^=ans,a^=ans;
          temp.x[0]=x,temp.x[1]=y,temp.w=a;
          Insert(temp);
        }else{
          read(x),read(y),read(a),read(b),read(k);
          x^=ans,y^=ans,a^=ans,b^=ans,k^=ans;
          cnt=len1=len2=cnt1=cnt2=0;
          f[0]=x-1,f[1]=y-1,dfs(root,f,k1,len1,t1,cnt1);
          f[0]=a,f[1]=y-1,dfs(root,f,k2,len2,t2,cnt2);
          f[0]=x-1,f[1]=b,dfs(root,f,k2,len2,t2,cnt2);
          f[0]=a,f[1]=b,dfs(root,f,k1,len1,t1,cnt1);
          cnt=cnt1-cnt2;
          for(i=0;i<len1;++i)cnt+=k1[i]->size;
          for(i=0;i<len2;++i)cnt-=k2[i]->size;
          if(cnt<k)
            puts("NAIVE!ORZzyz."),ans=0;
          else{
            std::sort(t1+1,t1+cnt1+1);
            std::sort(t2+1,t2+cnt2+1);
            ans=query(1,oo,1,cnt1,1,cnt2,k);
            printf("%d
    ",ans);
          }
        }
      }
      return 0;
    }
    View Code
  • 相关阅读:
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(8) 权限管理,自定义权限,扩展权限
    致博客园网友
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(7.2) 模块管理,模块的添加、修改、删除
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(7.1) 模块管理,验证权限,展示模块列表
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(6) 控制器基类 主要做登录用户、权限认证、日志记录等工作
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.5) 登录功能的实现,完善登录功能
    【C#公共帮助类】 WebHelper帮助类
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.4) 登录功能的实现,创建与登录用户相关的接口和实现类
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.3) 登录功能的实现,丰富数据表、建立关联
    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.2) 登录功能的实现,接口注入、log4net的使用
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8179089.html
Copyright © 2020-2023  润新知