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
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
麻麻我树套树一A辣!!
NAIVE!ORZzyz.
3
这题一看就是树套树的裸题啊
首先要查k小值,那么就要在外面来颗权值线段树,然后像主席树查询一样查询,那么就需要排名,排名是矩形里的点的个数,用K-D树维护一下就好了!。
代码略长
#include <stdio.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using std::min;
using std::max;
using std::nth_element;
const double alpha = 0.755;
const int MAXN = 100005;
const int inf = 1000000000;
int now,x0,x1,y0,y1,len,Ans,n,Q;
template<typename _t>
inline _t read(){
_t x=0,f=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
for(;isdigit(ch);ch=getchar())x=x*10+(ch^48);
return x*f;
}
struct Point{
int d[2];
inline int& operator [](int x){return d[x];}
inline bool operator < (const Point &a)const{
return d[now]==a.d[now]?d[now^1]<a.d[now^1]:d[now]<a.d[now];
}
}pt[MAXN];
struct node{
node *ls,*rs;
Point point;
int mn[2],mx[2],s,split;
inline void Update(node *p){
if(!p)return;
for(int i=0;i<=1;i++)mn[i]=min(mn[i],p->mn[i]);
for(int i=0;i<=1;i++)mx[i]=max(mx[i],p->mx[i]);
}
inline void Maintain(){
s=1;mn[0]=mx[0]=point[0];mn[1]=mx[1]=point[1];
if(ls)s+=ls->s,Update(ls);
if(rs)s+=rs->s,Update(rs);
}
inline bool in(int x0,int y0,int x1,int y1){
return x0<=mn[0]
&& x1>=mx[0]
&& y0<=mn[1]
&& y1>=mx[1];
}
inline bool out(int x0,int y0,int x1,int y1){
return mn[0]>x1
|| mx[0]<x0
|| mn[1]>y1
|| mx[1]<y0;
}
inline bool self(int x0,int y0,int x1,int y1){
return point[0]>=x0
&& point[0]<=x1
&& point[1]>=y0
&& point[1]<=y1;
}
node(Point x,int sp){
split = sp;
ls = rs= NULL;
point = x;s=1;
mn[0]=mx[0]=x[0];
mn[1]=mx[1]=x[1];
}
node(){}
void* operator new(size_t);
void operator delete(void *p);
#define size(x) ((x)?(x)->s:(0))
inline bool bad(){return size(ls)>=s*alpha||size(rs)>=s*alpha;}
}*C,*mempool,*need;
std::vector<node*>bin;
void build(node *&o,int l,int r,int d=0){
if(l>r){o=NULL;return;}
now = d;int mid = l+r>>1;
nth_element(&pt[l],&pt[mid],&pt[r+1]);
o = new node(pt[mid],now);
build(o->ls,l,mid-1,d^1);
build(o->rs,mid+1,r,d^1);
o->Maintain();
}
void* node :: operator new(size_t){
node *p;
if(!bin.empty()){
p = bin.back();
bin.pop_back();
}
else{
if(C==mempool){
C=new node[1<<15];
mempool=C+(1<<15);
}
p=C++;
}
return p;
}
void node::operator delete(void* p){
bin.push_back((node*)p);
}
int Query(node *o){
if(!o)return 0;
if(o->in(x0,y0,x1,y1))return o->s;
if(o->out(x0,y0,x1,y1))return 0;
int Ans = 0;
if(o->self(x0,y0,x1,y1))Ans ++;
return Ans+Query(o->ls)+Query(o->rs);
}
void dfs(node *p){
if(!p)return;
dfs(p->ls);
pt[++len]=p->point;
dfs(p->rs);
delete p;
}
inline void rebuild(node *&o){
len = 0;
register int split = o->split;dfs(o);
build(o,1,len,split);
}
void insert(node *&o,Point po,int d=0){
if(!o){o=new node(po,d);return;}
if(po[d]<o->point[d])insert(o->ls,po,d^1);
else insert(o->rs,po,d^1);
o->Maintain();
if(o->bad())need = o;
}
inline void ins(node *&o,Point po){
need = NULL;
insert(o,po);
if(need!=NULL)rebuild(need);
}
struct Seg_tree{
Seg_tree *ls,*rs;
node *root;
Seg_tree(){
ls=rs=NULL;
root=NULL;
}
}*root;
void Seg_insert(Seg_tree *&o,int l,int r,Point x,int val){
if(!o) o = new Seg_tree();
ins(o->root,x);
if(l==r)return;
int mid = l+r>>1;
if(val<=mid)Seg_insert(o->ls,l,mid,x,val);
else Seg_insert(o->rs,mid+1,r,x,val);
}
inline int Seg_Query(Seg_tree *o){
if(!o)return 0;
return Query(o->root);
}
inline void Ask(){
x0=read<int>()^Ans,y0=read<int>()^Ans,x1=read<int>()^Ans,y1=read<int>()^Ans;
register int k = read<int>()^Ans;
if(Seg_Query(root)<k){
Ans = 0;
printf("NAIVE!ORZzyz.\n");
return;
}
int l=1,r=inf;
Seg_tree *rt=root;
while(l<r){
int mid = l+r>>1,ans=Seg_Query(rt->rs);
if(k>ans)k-=ans,rt=rt->ls,r=mid;
else rt=rt->rs,l=mid+1;
}
printf("%d\n",Ans=l);
}
inline void change(){
Point cur;
cur[0]=read<int>()^Ans;cur[1]=read<int>()^Ans;
int val = read<int>()^Ans;
Seg_insert(root,1,inf,cur,val);
}
int main(){
n=read<int>();Q=read<int>();
while(Q--){
register int tmp = read<int>();
if(tmp == 1)change();
else Ask();
}
}