zoukankan      html  css  js  c++  java
  • BZOJ4605 : 崂山白花蛇草水

    外层维护权值线段树,内层维护kd-tree。

    修改的时候只往右儿子里插入,不平衡的时候替罪羊式重构。

    查询的时候在外层线段树上走,在内层kd-tree上查询矩形内点数即可。

    时间复杂度$O(qlog v(log^2q+sqrt{q}))$。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const double A=0.8;
    const int N=100010,M=1600010;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int n,ans,cmp_d,op,X1,Y1,X2,Y2,k;
    int tmp[N],deep,need[N],cnt,cur;
    int T[M],l[M],r[M],tot=1;
    struct node{int d[2],l,r,Max[2],Min[2],size;}t[M];
    inline bool cmp(int a,int b){return t[a].d[cmp_d]<t[b].d[cmp_d];}
    inline void umax(int&a,int b){if(a<b)a=b;}
    inline void umin(int&a,int b){if(a>b)a=b;}
    inline void up(int x){
      t[x].size=1+t[t[x].l].size+t[t[x].r].size;
      if(t[x].l){
        umax(t[x].Max[0],t[t[x].l].Max[0]);
        umin(t[x].Min[0],t[t[x].l].Min[0]);
        umax(t[x].Max[1],t[t[x].l].Max[1]);
        umin(t[x].Min[1],t[t[x].l].Min[1]);
      }
      if(t[x].r){
        umax(t[x].Max[0],t[t[x].r].Max[0]);
        umin(t[x].Min[0],t[t[x].r].Min[0]);
        umax(t[x].Max[1],t[t[x].r].Max[1]);
        umin(t[x].Min[1],t[t[x].r].Min[1]);
      }
    }
    int build(int l,int r,int D){
      int mid=(l+r)>>1;
      cmp_d=D;
      nth_element(need+l+1,need+mid+1,need+r+1,cmp);
      int x=need[mid];
      t[x].Max[0]=t[x].Min[0]=t[x].d[0];
      t[x].Max[1]=t[x].Min[1]=t[x].d[1];
      if(l!=mid)t[x].l=build(l,mid-1,!D);else t[x].l=0;
      if(r!=mid)t[x].r=build(mid+1,r,!D);else t[x].r=0;
      up(x);
      return x;
    }
    void dfs(int x){if(x)need[++cnt]=x,dfs(t[x].l),dfs(t[x].r);}
    inline void ins(int&root,int now){
      if(!root){root=now;return;}
      for(int D=deep=0,x=root;;D^=1){
        tmp[++deep]=x;
        umax(t[x].Max[0],t[now].Max[0]);
        umax(t[x].Max[1],t[now].Max[1]);
        umin(t[x].Min[0],t[now].Min[0]);
        umin(t[x].Min[1],t[now].Min[1]);
        t[x].size++;
        if(t[now].d[D]>=t[x].d[D]){
          if(!t[x].r){t[x].r=now;break;}else x=t[x].r;
        }else{
          if(!t[x].l){t[x].l=now;break;}else x=t[x].l;
        }
      }
      tmp[++deep]=now;
      if(deep<log(t[root].size)/log(1/A))return;
      while((double)t[t[now].l].size<A*t[now].size&&(double)t[t[now].r].size<A*t[now].size)now=tmp[--deep];
      if(!now)return;
      if(now==root){
        cnt=0,dfs(root);
        root=build(1,cnt,0);
        return;
      }
      int y=tmp[--deep];
      cnt=0,dfs(now);
      int k=build(1,cnt,deep&1);
      if(t[y].l==now)t[y].l=k;else t[y].r=k;
    }
    void ask(int x){
      if(!x||t[x].Max[0]<X1||t[x].Min[0]>X2||t[x].Max[1]<Y1||t[x].Min[1]>Y2||ans>=k)return;
      if(t[x].Min[0]>=X1&&t[x].Max[0]<=X2&&t[x].Min[1]>=Y1&&t[x].Max[1]<=Y2){ans+=t[x].size;return;}
      if(t[x].d[0]>=X1&&t[x].d[0]<=X2&&t[x].d[1]>=Y1&&t[x].d[1]<=Y2)ans++;
      ask(t[x].l);ask(t[x].r);
    }
    inline void add(){
      int x=1,a=1,b=1000000000,mid,flag=1;
      while(1){
        if(flag){
          cur++;
          t[cur].Max[0]=t[cur].Min[0]=t[cur].d[0]=X1;
          t[cur].Max[1]=t[cur].Min[1]=t[cur].d[1]=Y1;
          t[cur].size=1;
          ins(T[x],cur);
        }
        if(a==b)return;
        mid=(a+b)>>1;
        if(k<=mid){
          if(!l[x])l[x]=++tot;
          x=l[x],b=mid,flag=0;
        }else{
          if(!r[x])r[x]=++tot;
          x=r[x],a=mid+1,flag=1;
        }
      }
    }
    inline void query(){
      ans=0,ask(T[1]);
      if(ans<k){
        puts("NAIVE!ORZzyz.");
        ans=0;
        return;
      }
      int x=1,a=1,b=1000000000,mid;
      while(a<b){
        mid=(a+b)>>1;
        ans=0,ask(T[r[x]]);
        if(ans>=k)x=r[x],a=mid+1;else k-=ans,x=l[x],b=mid;
      }
      printf("%d
    ",ans=a);
    }
    int main(){
      read(n),read(n);
      while(n--){
        read(op),read(X1),read(Y1);X1^=ans,Y1^=ans;
        if(op==1){
          read(k);k^=ans;
          add();
        }else{
          read(X2),read(Y2),read(k);X2^=ans;Y2^=ans;k^=ans;
          query();
        }
      }
      return 0;
    }
    

      

  • 相关阅读:
    NHibernate 入门必看——NHibernate Made Simple
    ASP.NET 的多线程
    asp.net 禁止用户二次登录(转)
    marquee标记用法及在asp.net中的应用(转)
    解决Visual Studio 2005显示中文乱码(zhuan)
    ms sql 触发器( 转)
    Asp.net 页面导航的几种方法与比较
    ASP.NET1.1(VB):DataGrid中"加入序号列"和"截取定长字符串追加'...
    解决“Internet Explorer 无法打开 Internet站点已终止操作”问题(转)
    ASP.NET 2.0的页面指令集(转)
  • 原文地址:https://www.cnblogs.com/clrs97/p/5518385.html
Copyright © 2011-2022 走看看