您的位置:首页 > 其它

bzoj4604 The kth maximum number && bzoj4605 崂山白花蛇草水

2016-12-18 23:36 363 查看
(bzoj4604为bzoj4605弱化版)

bzoj4605

【题意】

n次操作,操作有2种:

1.平面上单点点权赋值,保证每个点最多赋值1次。

2.查询矩形点权第k大。

强制在线。

【数据范围】

n<=100000,点权<=w=10^9

【思路】

若改成序列问题,可以使用权值线段树套线段树。

矩形问题可以考虑把内层线段树改为kd-tree。

故本题使用权值线段树套kd-tree。

kd-tree有两种重构方式:定时重构,替罪羊重构。我使用了替罪羊重构。

【时间复杂度】

O(n*sqrt(n)*log w)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
#define top 1000000000
#define alpha 0.77
using namespace std;

struct tt{int l, r, d[2], mx[2], mn[2], size;}t[N*35];
struct tt1{int l, r, root;}t1[N*35];
struct aa{int d[2], id;}a
;
int n, m, lastans, temp, l, x, y, z, x1, x2, y1, y2, D, l1, xx, fx, k, l2, rt;

inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}

bool operator<(aa a, aa b){return a.d[D]<b.d[D];}

void update(int i){
for(int j=0; j<=1; j++){
t[i].mx[j]=t[i].mn[j]=t[i].d[j];
if(t[i].l){
t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);
}
if(t[i].r){
t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);
}
}
}

void kd_ins(int i, int x, int y, int now){
t[i].size++;
if(!now){
if(x<=t[i].d[0]){
if(!t[i].l){
l++; t[i].l=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].l, x, y, now^1);
}else{
if(!t[i].r){
l++; t[i].r=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].r, x, y, now^1);
}
}else{
if(y<=t[i].d[1]){
if(!t[i].l){
l++; t[i].l=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].l, x, y, now^1);
}else{
if(!t[i].r){
l++; t[i].r=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].r, x, y, now^1);
}
}
update(i);
if(max(t[t[i].l].size, t[t[i].r].size)>=t[i].size*alpha){xx=i; fx=0;}
if(xx&&t[i].l==xx)fx=i;
if(xx&&t[i].r==xx)fx=-i;
}

void kd_maketree(int L, int R, int now){
D=now; int mid=(L+R)>>1;
nth_element(a+L, a+mid, a+R+1);
rt=a[mid].id; t[rt].l=t[rt].r=0;
t[rt].d[0]=a[mid].d[0]; t[rt].d[1]=a[mid].d[1]; t[rt].size=R-L+1;
int p=rt;
if(L<mid){rt=0; kd_maketree(L, mid-1, now^1); t[p].l=rt;}
if(mid<R){rt=0; kd_maketree(mid+1, R, now^1); t[p].r=rt;}
update(p); rt=p;
}

void dfs(int i){
l2++; a[l2].d[0]=t[i].d[0]; a[l2].d[1]=t[i].d[1]; a[l2].id=i;
if(t[i].l)dfs(t[i].l);
if(t[i].r)dfs(t[i].r);
}
void sheep(int i){
l2=0; dfs(i);
rt=0; kd_maketree(1, l2, 0);
}

void dfs1(int i){
if(t[i].l)dfs1(t[i].l);
if(t[i].r)dfs1(t[i].r);
}

void ins1(int i, int L, int R, int x, int y, int z){
if(!t1[i].root){
l++; t1[i].root=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else{
xx=fx=0; kd_ins(t1[i].root, x, y, 0);
if(xx){
sheep(xx);
if(fx>0)t[fx].l=rt; if(fx<0)t[-fx].r=rt;
if(!fx)t1[i].root=rt;
}

}
if(L==R)return;
int mid=(L+R)>>1;
if(z<=mid){
if(!t1[i].l)t1[i].l=++l1;
ins1(t1[i].l, L, mid, x, y, z);
}else{
if(!t1[i].r)t1[i].r=++l1;
ins1(t1[i].r, mid+1, R, x, y, z);
}
}

int in(int x1, int x2, int y1, int y2, int X1, int X2, int Y1, int Y2){
return (X1<=x1)&&(x2<=X2)&&(Y1<=y1)&&(y2<=Y2);
}
int out(int x1, int x2, int y1, int y2, int X1, int X2, int Y1, int Y2){
return (X2<x1)||(x2<X1)||(Y2<y1)||(y2<Y1);
}

int csum(int i, int x1, int x2, int y1, int y2){
if(!i)return 0;
if(in(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1], x1, x2, y1, y2))return t[i].size;
if(out(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1], x1, x2, y1, y2))return 0;
int sum=0;
if(in(t[i].d[0], t[i].d[0], t[i].d[1], t[i].d[1], x1, x2, y1, y2))sum++;
sum+=csum(t[i].l, x1, x2, y1, y2)+csum(t[i].r, x1, x2, y1, y2); return sum;
}

int check1(int i, int L, int R, int x1, int x2, int y1, int y2, int k){
if(L==R)return L;
int sum, mid=(L+R)>>1;
if(!t1[i].r)sum=0; else sum=csum(t1[t1[i].r].root, x1, x2, y1, y2);
if(sum>=k)return check1(t1[i].r, mid+1, R, x1, x2, y1, y2, k);
else return check1(t1[i].l, L, mid, x1, x2, y1, y2, k-sum);
}

int main(){
m=read(); n=read(); lastans=0;
l=0; l1=1; t1[1].l=t1[1].r=0;
for(int i=1; i<=n; i++){
temp=read();
if(temp==1){
x=read()^lastans; y=read()^lastans; z=read()^lastans;
ins1(1, 1, top, x, y, z);
}else{
x1=read()^lastans; y1=read()^lastans; x2=read()^lastans; y2=read()^lastans; k=read()^lastans;
if(csum(t1[1].root, x1, x2, y1, y2)<k){lastans=0; printf("NAIVE!ORZzyz.\n");}
else{lastans=check1(1, 1, top, x1, x2, y1, y2, k); printf("%d\n", lastans);}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: