版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82931452
题目链接:点击这里
解题思路:
这题被强制在线了如果是离线(BZOJ 2683)可以CDQ分治 + 树状数组做.
所以只能用KDtree了.
若每次都将新节点插入原DKT中,最终会导致树会非常的不平衡,而失去了意义,导致超时.
所以我们要设置一个阈值,当节点数到达阈值时就对KDT进行重构保证稳定.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int mx = 2e5 + 10;
const int mod = 1<<30;
typedef long long ll;
int n,m,now;
int x1,x2,y1,y2,z;
struct node
{
int mi[2],ma[2];
int l,r,d[2],siz,sum;
bool operator < (node A)const
{
return d[now] < A.d[now];
}
}s[mx];
void update(int rt,int to)
{
for(int i=0;i<2;i++){
s[rt].mi[i] = min(s[rt].mi[i],s[to].mi[i]);
s[rt].ma[i] = max(s[rt].ma[i],s[to].ma[i]);
}
s[rt].sum += s[to].sum;
}
int build(int l,int r,int rt)
{
int mid = (l+r)>>1;
now = rt;
nth_element(s+l,s+mid,s+r+1);
s[mid].sum = s[mid].siz;
for(int i=0;i<2;i++) s[mid].mi[i] = s[mid].ma[i] = s[mid].d[i];
if(l!=mid) s[mid].l = build(l,mid-1,rt^1); else s[mid].l = 0;
if(r!=mid) s[mid].r = build(mid+1,r,rt^1); else s[mid].r = 0;
if(l!=mid) update(mid,s[mid].l);
if(r!=mid) update(mid,s[mid].r);
return mid;
}
void insert(int rt,int p)
{
now = 0;
while(1){
update(rt,p);
if(s[rt].d[now]>s[p].d[now])
{
if(!s[rt].l){
s[rt].l = p;
return;
}
rt = s[rt].l;
}else{
if(!s[rt].r){
s[rt].r = p;
return ;
}
rt = s[rt].r;
}
now ^= 1;
}
}
bool in(int x,int y)
{
if(x>=x1&&x<=x2&&y>=y1&&y<=y2) return 1;
return 0;
}
int judge(int rt)
{
bool f1 = in(s[rt].mi[0],s[rt].mi[1]);
bool f2 = in(s[rt].ma[0],s[rt].ma[1]);
if(f1&&f2) return 1;
if(max(x1,s[rt].mi[0])>min(x2,s[rt].ma[0])) return -1;
if(max(y1,s[rt].mi[1])>min(y2,s[rt].ma[1])) return -1;
return 0;
}
int query(int rt)
{
int st = judge(rt);
if(st==-1) return 0;
if(st==1) return s[rt].sum;
if(in(s[rt].d[0],s[rt].d[1])) st = s[rt].siz;
return st + query(s[rt].l) + query(s[rt].r);
}
int main()
{
scanf("%d",&n);
int ans = 0,cnt = 0;
int root = 1,up = 10000;
while(scanf("%d",&z)&&z!=3)
{
if(z==1){
scanf("%d%d%d",&x1,&y1,&x2);
s[++cnt].d[0] = x1^ans;
s[cnt].d[1] = y1^ans;
s[cnt].sum = s[cnt].siz = x2^ans;
for(int i=0;i<2;i++) s[cnt].mi[i] = s[cnt].ma[i] = s[cnt].d[i];
if(cnt==up){
up += 10000;
root = build(1,cnt,0);
}else if(cnt!=1) insert(root,cnt);
}else{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1 ^= ans,y1 ^= ans,x2 ^= ans,y2 ^= ans;
if(x1>x2) swap(x1,x2);
if(y1>y2) swap(y1,y2);
ans = query(root);
printf("%d\n",ans);
}
}
return 0;
}