bzoj4605 崂山白花蛇草水 权值线段树套kd树

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/85081256

Description


Q次操作,要求资瓷

  1. 在(x,y)处放一个数字x
  2. 查询(x1,y1)到(x2,y2)矩形内第k大

Solution


非常裸的权值线段树套kd树,为了保证复杂度可以定期重构也可以平衡因子搞搞

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)

const double alpha=0.6;
const int N=100005;

struct treeNode1 {
	int l,r,p[2],mx[2],mn[2],sum,val;
} t1[N*40];

struct treeNode2 {
	int l,r,root;
} t2[N*40];

int v[N],tot,cnt,wjp,rec,ff,typ;

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void push_up(int x) {
	t1[x].sum=t1[x].val;
	t1[x].mn[0]=t1[x].mx[0]=t1[x].p[0];
	t1[x].mn[1]=t1[x].mx[1]=t1[x].p[1];
	if (t1[x].l) {
		t1[x].mx[0]=max(t1[x].mx[0],t1[t1[x].l].mx[0]);
		t1[x].mx[1]=max(t1[x].mx[1],t1[t1[x].l].mx[1]);
		t1[x].mn[0]=min(t1[x].mn[0],t1[t1[x].l].mn[0]);
		t1[x].mn[1]=min(t1[x].mn[1],t1[t1[x].l].mn[1]);
		t1[x].sum+=t1[t1[x].l].sum;
	}
	if (t1[x].r) {
		t1[x].mx[0]=max(t1[x].mx[0],t1[t1[x].r].mx[0]);
		t1[x].mx[1]=max(t1[x].mx[1],t1[t1[x].r].mx[1]);
		t1[x].mn[0]=min(t1[x].mn[0],t1[t1[x].r].mn[0]);
		t1[x].mn[1]=min(t1[x].mn[1],t1[t1[x].r].mn[1]);
		t1[x].sum+=t1[t1[x].r].sum;
	}
}

bool cmp(int a,int b) {
	return (t1[a].p[wjp]==t1[b].p[wjp])?(t1[a].p[!wjp]<t1[b].p[!wjp]):(t1[a].p[wjp]<t1[b].p[wjp]);
}

int build(int tl,int tr,int R) {
	int mid=(tl+tr)>>1; wjp=R;
	std:: nth_element(v+tl,v+mid,v+tr+1,cmp);
	if (tl!=mid) t1[v[mid]].l=build(tl,mid-1,!R);
	if (mid!=tr) t1[v[mid]].r=build(mid+1,tr,!R);
	push_up(v[mid]); return v[mid];
}

void dfs(int now) {
	v[++v[0]]=now;
	if (t1[now].l) dfs(t1[now].l);
	if (t1[now].r) dfs(t1[now].r);
	t1[now].l=t1[now].r=0;
	push_up(now);
}

void ins(int &now,int fa,int *p,int R) {
	if (!now) { now=++tot;
		t1[now].p[0]=t1[now].mx[0]=t1[now].mn[0]=p[0];
		t1[now].p[1]=t1[now].mx[1]=t1[now].mn[1]=p[1];
		t1[now].sum=t1[now].val=1;
		return ;
	}
	if (p[R]<t1[now].p[R]) ins(t1[now].l,now,p,!R);
	else ins(t1[now].r,now,p,!R);
	push_up(now);
	if (alpha*t1[now].sum<=t1[t1[now].l].sum) rec=now,ff=fa,typ=R;
	if (alpha*t1[now].sum<=t1[t1[now].r].sum) rec=now,ff=fa,typ=R;
}

void modify(int &now,int tl,int tr,int x,int *p) {
	if (!now) now=++cnt;
	rec=ff=typ=0;
	ins(t2[now].root,0,p,0);
	if (rec) {
		int d=(t1[ff].r==rec); v[0]=0;
		dfs(rec); int tmp=build(1,v[0],typ);
		if (ff) (d)?(t1[ff].r=tmp):(t1[ff].l=tmp);
		else t2[now].root=tmp;
	}
	if (tl==tr) return ;
	int mid=(tl+tr)>>1;
	if (x<=mid) modify(t2[now].l,tl,mid,x,p);
	else modify(t2[now].r,mid+1,tr,x,p);
}

bool check(int now,int x1,int y1,int x2,int y2) {
	if (t1[now].mx[0]<x1||t1[now].mn[0]>x2) return false;
	if (t1[now].mx[1]<y1||t1[now].mn[1]>y2) return false;
	return true;
}

int ask(int now,int x1,int y1,int x2,int y2) {
	if (!check(now,x1,y1,x2,y2)) return 0;
	if (t1[now].mn[0]>=x1&&t1[now].mx[0]<=x2&&t1[now].mn[1]>=y1&&t1[now].mx[1]<=y2) return t1[now].sum;
	int res=t1[now].val*(t1[now].p[0]>=x1&&t1[now].p[0]<=x2&&t1[now].p[1]>=y1&&t1[now].p[1]<=y2);
	res+=ask(t1[now].l,x1,y1,x2,y2);
	res+=ask(t1[now].r,x1,y1,x2,y2);
	return res;
}

int query(int now,int tl,int tr,int k,int x1,int y1,int x2,int y2) {
	if (tl==tr) return tl;
	int mid=(tl+tr)>>1,w=ask(t2[t2[now].l].root,x1,y1,x2,y2);
	if (w>=k) return query(t2[now].l,tl,mid,k,x1,y1,x2,y2);
	return query(t2[now].r,mid+1,tr,k-w,x1,y1,x2,y2);
}

int main(void) {
	int n=read(),T=read(),lxf=0;
	for (int lastans=0;T--;) {
		int opt=read();
		if (opt==1) {
			int x=read()^lastans,y=read()^lastans,v=read()^lastans;
			int p[2]={x,y};
			modify(lxf,1,1000000000,v,p);
		} else {
			int x1=read()^lastans,y1=read()^lastans,x2=read()^lastans,y2=read()^lastans;
			int k=read()^lastans; int total=ask(t2[lxf].root,x1,y1,x2,y2);
			if (total<k) puts("NAIVE!ORZzyz."),lastans=0;
			else printf("%d\n", lastans=query(1,1,1000000000,total-k+1,x1,y1,x2,y2));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/85081256