4605: 崂山白花蛇草水
Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 527 Solved: 153
[Submit][Status][Discuss]
Description
神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水。凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了。蒟蒻Bob特地为他准备了999,999,999,999,999,999瓶崂山白花蛇草水,想要灌神犇Aleph。神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bob最终答应了他的请求,但蒟蒻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
NAIVE!ORZzyz.
3
外层权值线段树
内层kdtree
//做完之后 我觉得内层写二维线段树才是明智的选择
调试要注意的
替罪羊树重构
不要puhup当前根节点的fa
//万一是0就GG 但可以特判就是常数打 因为根本不会改变fa维护的信息
更可怕的就是把一个anc写成了ans...
//以后这俩再也不一起用了555
最可怕的就是
一会想在kdtree的模板套替罪羊
一会想在替罪羊的模板里套kdtree
最后发现在kdtree里写了个替罪羊 替罪羊里不知道哪里又换成了kdtree
调哭我
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef double db;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=500100,M=int(1e9),MN=4000100;
const db alpha=0.75;
int ans;
int cur;
struct node
{
int d[2],mn[2],mx[2],s[2],pos;
inline int& operator [](int x){return d[x];}
friend bool operator <(const node &x,const node &y){return x.d[cur]<y.d[cur];}
}st[N>>2],tr[MN];
int tot;
int fa[MN],size[MN];int num[2];
struct kdtree
{
node T;
int root,top,res;
kdtree(){top=root=0;}
inline void pushup(int k)
{
for(int i=0;i<2;++i)
{
tr[k].mn[i]=tr[k].mx[i]=tr[k][i];
if(tr[k].s[0])
tr[k].mn[i]=min(tr[k].mn[i],tr[tr[k].s[0]].mn[i]),
tr[k].mx[i]=max(tr[k].mx[i],tr[tr[k].s[0]].mx[i]);
if(tr[k].s[1])
tr[k].mn[i]=min(tr[k].mn[i],tr[tr[k].s[1]].mn[i]),
tr[k].mx[i]=max(tr[k].mx[i],tr[tr[k].s[1]].mx[i]);
}
size[k]=size[tr[k].s[0]]+size[tr[k].s[1]]+1;
}
inline bool balance(int k)
{return alpha*size[k]>=db(max(size[tr[k].s[0]],size[tr[k].s[1]]));}
void dfs(int k)
{
if(!k)return ;
st[++top]=tr[k];
dfs(tr[k].s[0]);dfs(tr[k].s[1]);
}
int build(int l,int r,int now)
{
if(l>r)return 0;
cur=now;
int mid=(l+r)>>1,k;
nth_element(st+l,st+mid,st+r+1);
k=st[mid].pos;
tr[k].s[0]=build(l,mid-1,now^1);
tr[k].s[1]=build(mid+1,r,now^1);
if(tr[k].s[0])fa[tr[k].s[0]]=k;
if(tr[k].s[1])fa[tr[k].s[1]]=k;
pushup(k);
return k;
}
void rebuild(int k,int d)
{
top=0;dfs(k);
int anc=fa[k],son=(tr[anc].s[1]==k),now=build(1,top,d);
fa[now]=anc;
if(anc)tr[anc].s[son]=now;
if(k==root)root=now;
}
void insert(int x,int y)
{
tr[++tot][0]=x;tr[tot][1]=y;
tr[tot].pos=tot;
pushup(tot);
if(!root) {root=tot;return ;}
int k=root,now(0),son,inv(0);
while(1)
{
son=(tr[tot][now]>=tr[k][now]);
if(!tr[k].s[son])
{tr[k].s[son]=tot;fa[tot]=k;break;}
else k=tr[k].s[son];
now^=1;
}
while(k)
{
pushup(k);
if(!balance(k)) inv=k,son=now;
k=fa[k];now^=1;
}
if(inv)rebuild(inv,son);
}
inline bool in(int a,int b,int c,int d)
{return a<=T.mn[0] && c>=T.mx[0] && b<=T.mn[1] && d>=T.mx[1];}
inline bool out(int a,int b,int c,int d)
{return a>T.mx[0] || c<T.mn[0] || b>T.mx[1] || d<T.mn[1];}
inline bool node_in(int a,int b,int c,int d)
{return a<=T[0] && c>=T[0] && b<=T[1] && d>=T[1];}
void query(int k,int a,int b,int c,int d)
{
if(!k)return ;
T=tr[k];
if(in(a,b,c,d)){res+=size[k];return ;}
if(out(a,b,c,d))return ;
if(node_in(a,b,c,d))res++;
query(tr[k].s[0],a,b,c,d);
query(tr[k].s[1],a,b,c,d);
return ;
}
int kdquery(int a,int b,int c,int d)
{
res=0;query(root,a,b,c,d);
return res;
}
}kd[MN];
struct seg_tree{int ls,rs;}str[MN];
int root,sz;
void insert(int &k,int l,int r,int val,int x,int y)
{
if(!k)k=++sz;
kd[k].insert(x,y);
if(l==r)return ;
int mid((l+r)>>1);
val<=mid ? insert(str[k].ls,l,mid,val,x,y) : insert(str[k].rs,mid+1,r,val,x,y);
}
void query(int k,int l,int r,int a,int b,int c,int d,int rk)
{
if(l==r){ans=l;return ;}
int mid((l+r)>>1);
int tmp=kd[str[k].rs].kdquery(a,b,c,d);
tmp>=rk ? query(str[k].rs,mid+1,r,a,b,c,d,rk) : query(str[k].ls,l,mid,a,b,c,d,rk-tmp);
}
int main()
{
int n=read(),Q=read();
register int opt,a,b,c,d,val;
while(Q--)
{
opt=read();
a=read()^ans;b=read()^ans;
switch(opt)
{
case 1:
val=read()^ans;
insert(root,1,M,val,a,b);
break;
case 2:
c=read()^ans;d=read()^ans;
val=read()^ans;
if(a>c)swap(a,c);
if(b>d)swap(b,d);
if(kd[1].kdquery(a,b,c,d)<val)
ans=0,puts("NAIVE!ORZzyz.");
else
query(root,1,M,a,b,c,d,val),
print(ans),puts("");
break;
}
}
return 0;
}