P4848 崂山白花蛇草水
• 平面是二维的,第 K 大是相对的。
• 单纯的 K- D 似乎并不能解决(反正我不会)。
• 第 K 大和二分是紧密相关的。
• 二分之后的判定就是一个二维数点问题。
• 所以我们可以线段树套 K-D tree 。
1 #include<bits/stdc++.h> 2 #define ls son[u][0] 3 #define rs son[u][1] 4 using namespace std; 5 const double dat=0.8; 6 const int N=1000000000; 7 int n,m,cnt,tot,rt,ans; 8 int opt,x[2],y[2],w,sum; 9 int root[5000050]; 10 int ch[5000050][2]; 11 int val[5000050][2],siz[5000050]; 12 int L[5000050][2],R[5000050][2]; 13 int son[5000050][2]; 14 int t[5000050],top,K; 15 bool cmp(int a,int b) 16 { 17 return val[a][K]<val[b][K]; 18 } 19 void pushup(int u) 20 { 21 siz[u]=siz[ls]+siz[rs]+1; 22 for(int i=0;i<=1;++i) 23 { 24 L[u][i]=min(val[u][i],min(L[ls][i],L[rs][i])); 25 R[u][i]=max(val[u][i],max(R[ls][i],R[rs][i])); 26 } 27 } 28 void dfs(int u) 29 { 30 t[++top]=u; 31 if(ls) dfs(ls); 32 if(rs) dfs(rs); 33 } 34 void calc_build(int &u,int l,int r,int k) 35 { 36 if(l>r) 37 { 38 u=0; 39 return ; 40 } 41 int mid=(l+r)>>1; K=k; 42 sort(t+l,t+r+1,cmp); u=t[mid]; 43 calc_build(ls,l,mid-1,k^1); 44 calc_build(rs,mid+1,r,k^1); 45 pushup(u); 46 } 47 void calc_rebuild(int &u,int k) 48 { 49 t[top=1]=tot;dfs(u); 50 calc_build(u,1,top,k); 51 } 52 void calc_insert(int &u,int k) 53 { 54 if(!u) 55 u=tot; 56 else if(val[tot][k]<val[u][k]) 57 { 58 if(siz[ls]>siz[u]*dat) 59 { 60 calc_rebuild(u,k); 61 return ; 62 } 63 else 64 calc_insert(ls,k^1); 65 } 66 else 67 { 68 if(siz[rs]>siz[u]*dat) 69 { 70 calc_rebuild(u,k); 71 return ; 72 } 73 else 74 calc_insert(rs,k^1); 75 } 76 pushup(u); 77 return ; 78 } 79 void calc_add(int &u,int l,int r,int pos) 80 { 81 if(!u) u=++cnt; 82 ++tot; 83 val[tot][0]=x[0]; 84 val[tot][1]=x[1]; 85 calc_insert(root[u],0); 86 if(l==r) return ; 87 int mid=(l+r)>>1; 88 if(pos<=mid) calc_add(ch[u][0],l,mid,pos); 89 else calc_add(ch[u][1],mid+1,r,pos); 90 } 91 bool flagALL; 92 bool flagALO; 93 bool flagBIT; 94 void check(int u) 95 { 96 flagALL=true; flagBIT=true; flagALO=true; 97 for(int i=0;i<=1;++i) 98 if(L[u][i]<x[i]||R[u][i]>y[i]) 99 { 100 flagALL=false; 101 if(val[u][i]>y[i]||val[u][i]<x[i]) 102 { 103 flagALO=false; 104 if(L[u][i]>y[i]||R[u][i]<x[i]) 105 flagBIT=false; 106 } 107 } 108 } 109 void ask(int u) 110 { 111 if(!u) return ; 112 check(u); 113 if(flagALL) 114 { 115 sum+=siz[u]; 116 return ; 117 } 118 if(flagALO) 119 sum+=1; 120 if(!flagBIT) 121 return ; 122 ask(ls); ask(rs); 123 } 124 void calc_ask(int u,int l,int r) 125 { 126 if(l==r) 127 { 128 sum=0; ask(root[u]); 129 ans=sum>=w? l:0; 130 return ; 131 } 132 int mid=(l+r)>>1; 133 sum=0; ask(root[ch[u][1]]); 134 if(w>sum) 135 { 136 w-=sum; 137 calc_ask(ch[u][0],l,mid); 138 } 139 else 140 calc_ask(ch[u][1],mid+1,r); 141 } 142 int main() 143 { 144 L[0][0]=N; L[0][1]=N; 145 R[0][0]=0; R[0][1]=0; 146 scanf("%d%d",&n,&m); 147 while(m--) 148 { 149 scanf("%d%d%d",&opt,&x[0],&x[1]); 150 x[0]^=ans; x[1]^=ans; 151 if(opt==1) 152 { 153 scanf("%d",&w); w^=ans; 154 calc_add(rt,1,N,w); 155 } 156 else 157 { 158 scanf("%d%d%d",&y[0],&y[1],&w); 159 y[0]^=ans; y[1]^=ans; w^=ans; 160 calc_ask(rt,1,N); 161 if(!ans) printf("NAIVE!ORZzyz.\n"); 162 else printf("%d\n",ans); 163 } 164 } 165 return 0; 166 }