【崂山白花蛇草水】权值线段树套kd-tree
感觉自己过得十分地卡orz,大常数玩家瑟瑟发抖。
BZOJ4605
LUOGU4848
4605: 崂山白花蛇草水
Time Limit: 80 Sec Memory Limit: 512 MB Submit: 700 Solved: 218 [Submit][Status][Discuss]Description
神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水。凭借着神犇Aleph的实
力,他轻松地进了山东省省队,现在便是他履行诺言的时候了。蒟蒻Bob特地为他准备了999,999,999,999,999,999
瓶崂山白花蛇草水,想要灌神犇Aleph。神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bo
b最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答一些问题。具体说来,蒟蒻Bob会在一个宽敞
的广场上放置一些崂山白花蛇草水(可视为二维平面上的一些整点),然后询问神犇Aleph在矩形区域(x1, y1), (
x2, y2)(x1≤x2且y1≤y2,包括边界)中,崂山白花蛇草水瓶数第k多的是多少。为了避免麻烦,蒟蒻Bob不会在同
一个位置放置两次或两次以上的崂山白花蛇草水,但蒟蒻Bob想为难一下神犇Aleph,希望他能在每次询问时立刻回
答出答案。神犇Aleph不屑于做这种问题,所以把这个问题交给了你。
Input
输入的第一行为两个正整数N, Q,表示横纵坐标的范围和蒟蒻Bob的操作次数(包括放置次数和询问次数)。
接下来Q行,每行代表蒟蒻Bob的一个操作,操作格式如下:
首先第一个数字type,表示操作种类。type=1表示放置,type=2表示询问。
若type=1,接下来会有三个正整数x, y, v,表示在坐标整点(x, y)放置v瓶崂山白花蛇草水。(1≤x, y≤N, 1≤v≤10^9)
若type=2,接下来会有五个正整数x1, y1, x2, y2, k,表示询问矩形区域(x1, y1), (x2, y2)中,崂山白花蛇草水瓶数第k多的是多少。
(1≤x1≤x2≤N,1≤y1≤y2≤N,1≤k≤Q)
为了体现程序的在线性,你需要将每次读入的数据(除了type值)都异或lastans,其中lastans表示上次询问的答
案。如果上次询问的答案为"NAIVE!ORZzyz."(见样例输出),则将lastans置为0。初始时的lastans为0。
初始时平面上不存在崂山白花蛇草水。
本题共有12组测试数据。对于所有的数据,N≤500,000。
Q的范围见下表:
测试点1-2 Q=1,000
测试点3-7 Q=50,000
测试点8-12 Q=100,000
Output
对于每个询问(type=2的操作),回答崂山白花蛇草水瓶数第k多的是多少。若不存在第k多的瓶数,
请输出"NAIVE!ORZzyz."(输出不含双引号)。
Sample Input
10 7
1 1 1 1
1 2 2 3
1 4 1 2
1 3 4 4
2 1 1 4 1 3
2 2 2 3 5 4
2 2 1 4 4 2
Sample Output
NAIVE!ORZzyz.
NAIVE!ORZzyz.
3
HINT
Source
乍一眼看到这道题,由于刚做了K远点对,第一个想法是大小根堆A*乱搞一下,看了下K的范围orz。 好吧。我们发现求第K大的那个点的瓶数,这个我们可以想到主席树。所以说理论上外层套一个KD-TREE内层一个树上主席树,每次主席树提出log个点来搞应该是可以的。但是我们很容易发现他的常数有点爆炸,因为最关键的内层树时间复杂度总要跑满。那么我们可以换一下想法,外层套一个权值线段树,维护所有权值在区间点的KD-TREE,这样我们查询的时候看一下线段树右儿子的KD-TREE被包含是否有k个递归到右边,否则递归到左边,利用kd-tree判一下矩形是否有交和矩形是否覆盖既可。 code:// luogu-judger-enable-o2
#include<stdio.h>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 100005;
const int inf = 1e9;
int n,q;
struct node{
node *ls,*rs; int siz;
int sx[2],sy[2]; int x,y;
}z[maxn*40],*tl,*nul,**RT,*pool[maxn];
int lj;
bool isbad(node *&p) {
if(max(p->ls->siz,p->rs->siz)*4>p->siz*3) return 1;
return 0;
}
struct orz{
int xx,yy;
}sta[maxn]; int top;
void upd(node *&p) {
p->siz=1;
if(p->ls!=nul) {
p->sx[0] = min(p->sx[0],p->ls->sx[0]);
p->sx[1] = max(p->sx[1],p->ls->sx[1]);
p->sy[0] = min(p->sy[0],p->ls->sy[0]);
p->sy[1] = max(p->sy[1],p->ls->sy[1]);
p->siz+=p->ls->siz;
}
if(p->rs!=nul) {
p->sx[0] = min(p->sx[0],p->rs->sx[0]);
p->sx[1] = max(p->sx[1],p->rs->sx[1]);
p->sy[0] = min(p->sy[0],p->rs->sy[0]);
p->sy[1] = max(p->sy[1],p->rs->sy[1]);
p->siz+=p->rs->siz;
}
}
node* nwnode(int x,int y) {
node* p = lj?pool[lj--]:++tl;
p->ls = p->rs = nul; p->siz = 1;
p->sx[0] = p->sx[1] = p->x = x;
p->sy[0] = p->sy[1] = p->y = y;
return p;
}
void tra(node *&p) {
if(p==nul)return;
tra(p->ls);
pool[++lj] = p;
++top;
sta[top].xx= p->x; sta[top].yy = p->y;
tra(p->rs);
}
bool cmpx(orz aa,orz bb) {
return aa.xx < bb.xx ;
}
bool cmpy(orz aa,orz bb) {
return aa.yy < bb.yy;
}
void build(node *&p,int l,int r,int nw) {
int mid = (l+r)>>1;
if(!nw) nth_element(sta+l,sta+mid,sta+r+1,cmpx);
else nth_element(sta+l,sta+mid,sta+r+1,cmpy);
p = nwnode(sta[mid].xx,sta[mid].yy);
if(l<mid) build(p->ls,l,mid-1,nw^1);
if(mid<r) build(p->rs,mid+1,r,nw^1);
upd(p);
}
void rebuild() {
if(*RT==nul) return;
top = 0;
tra(*RT);
if(top>0) build(*RT,1,top,0);
else *RT = nul;
RT = &nul;
}
int XA,YA,XB,YB,VV;
void inskd(node *&p,int nw) {
if(p==nul) {
p = nwnode(XA,YA);
return;
}
if(nw==0) {
XA<=p->x?inskd(p->ls,nw^1):inskd(p->rs,nw^1);
} else {
YA<=p->y?inskd(p->ls,nw^1):inskd(p->rs,nw^1);
}
upd(p);
if(isbad(p)) RT = &p;
}
bool panj(node *&p) {
int xo1 = max(p->sx[0],XA);
int yo1 = min(p->sy[1],YB);
int xo2 = min(p->sx[1],XB);
int yo2 = max(p->sy[0],YA);
if(xo1<=xo2&&yo2<=yo1) return 1;
return 0;
}
bool baohan(node *&p) {
if(XA<=p->sx[0]&&p->sx[1]<=XB&&YA<=p->sy[0]&&p->sy[1]<=YB) return 1;
return 0;
}
bool dianh(node *&p) {
if(XA<=p->x&&p->x<=XB&&YA<=p->y&&p->y<=YB) return 1;
return 0;
}
int kdquery(node *&p) {
if(p==nul||p==NULL) return 0;
if(!panj(p)) return 0;
if(baohan(p)) return p->siz;
return kdquery(p->ls) + kdquery(p->rs) + dianh(p);
}
struct nod{
int ls,rs;
node *rt;
}dt[maxn*40]; int tot;
int rrt;
void init() {
tl = nul = z;
nul->ls = nul->rs = nul;
rrt = ++tot; dt[rrt].rt = nul;
RT = &nul;
}
void zxins(int &p,int l,int r) {
if(!p) {
p = ++tot; dt[p].rt = nul;
}
inskd(dt[p].rt,0);
if(*RT!=nul) rebuild();
if(l==r) return;
int mid = (l+r)>>1;
if(VV<=mid) zxins(dt[p].ls,l,mid);
else zxins(dt[p].rs,mid+1,r);
}
int query(int &p,int l,int r,int k) {
if(!p) {
p = ++tot; dt[p].rt = nul;
}
if(l==r) return l;
int mid = (l+r)>>1;
int rsz = dt[p].rs ? kdquery(dt[dt[p].rs].rt) : 0;
if(rsz>=k) return query(dt[p].rs,mid+1,r,k);
else return query(dt[p].ls,l,mid,k-rsz);
}
int main() {
init();
scanf("%d%d",&n,&q);
int type,k;
int lastans = 0;
for(int i=1;i<=q;i++) {
scanf("%d",&type);
if(type==1) {
scanf("%d%d%d",&XA,&YA,&VV);
XA^=lastans; YA^=lastans; VV^=lastans;
zxins(rrt,1,inf);
} else {
scanf("%d%d%d%d%d",&XA,&YA,&XB,&YB,&k);
XA^=lastans; YA^=lastans; XB^=lastans; YB^=lastans; k^=lastans;
if(XA>XB) swap(XA,XB);
if(YA>YB) swap(YA,YB);
if( kdquery(dt[rrt].rt ) <k ) puts("NAIVE!ORZzyz."),lastans=0;
else {
lastans = query(rrt,1,inf,k);
printf("%d\n",lastans);
}
}
}
}

浙公网安备 33010602011771号