题目描述

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

Idea By Aleph, Description & Data cases By jinlifu1999.

分析

本题强制在线,显然是一道数据结构题,维护的是一个二维区间,想到树套树或者K-D树,还要寻找第k大,所以还需要再套一棵树。树套树套树编码难度和常数都很大,所以我们选择K-D树。另一棵树显然有很多种选择,但是显然线段树是我们最佳的选择,因为它的形态不会改变。由于K-D树随着节点的增加会变得不平衡,我们可以使用类似替罪羊树的重建方法对K-D树进行部分重构,如果放外层重建的时空开销会比较大。所以我们外层维护一棵权值线段树,内层维护一棵K-D树即可时间复杂度O(nn−−√log2n)O(n\sqrt nlog_2n)。

代码

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#define alpha 0.77
#define MAXV 1000000000
#define MAXN 100000
using namespace std;
int n,Q,ans;
void Read(int &x){char c;while(c=getchar(),c!=EOF)if(c>='0'&&c<='9'){x=c-'0';while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';ungetc(c,stdin);return;}
}
namespace K_DTree{
int D;
bool rbd;
struct node{int d[2],mn[2],mx[2],cnt,sum;node *ch[2];inline node(){}inline node(int x,int y):cnt(1){d[0]=mn[0]=mx[0]=x,d[1]=mx[1]=mn[1]=y;}inline bool operator<(const node &b)const{return d[D]<b.d[D];}inline bool operator==(const node &b)const{return d[0]==b.d[0]&&d[1]==b.d[1];}
}now,tree[MAXN*25+10],*tcnt=tree,*v[MAXN+10],**vcnt,**rbt;
inline bool cmp(node *x,node *y){return x->d[D]<y->d[D];
}
inline int Get_sum(node *p){return p?p->sum:0;
}
inline bool in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){return x1<=X1&&X2<=x2&&y1<=Y1&&Y2<=y2;
}
inline bool out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){return x1>X2||x2<X1||y1>Y2||y2<Y1;
}
inline bool balance(node *p){return p->sum*alpha>=max(Get_sum(p->ch[0]),Get_sum(p->ch[1]));
}
void update(node *p){for(int i=0;i<2;i++){p->mx[i]=p->mn[i]=p->d[i];if(p->ch[0])p->mn[i]=min(p->mn[i],p->ch[0]->mn[i]),p->mx[i]=max(p->mx[i],p->ch[0]->mx[i]);if(p->ch[1])p->mn[i]=min(p->mn[i],p->ch[1]->mn[i]),p->mx[i]=max(p->mx[i],p->ch[1]->mx[i]);}p->sum=Get_sum(p->ch[0])+Get_sum(p->ch[1])+p->cnt;
}
void rebuild(node *&p,int l,int r,bool f){if(l>r)return;D=f;int mid=(l+r)>>1;nth_element(v+l,v+mid,v+r+1,cmp);p=v[mid];p->ch[0]=p->ch[1]=0;rebuild(p->ch[0],l,mid-1,f^1);rebuild(p->ch[1],mid+1,r,f^1);update(p);
}
void travel(node *p){if(!p)return;*++vcnt=p;travel(p->ch[0]);travel(p->ch[1]);
}
void insert(node *&p,bool D){if(!p){p=++tcnt;p->cnt=p->sum=0;p->ch[0]=p->ch[1]=0;p->d[0]=p->mn[0]=p->mx[0]=now.d[0];p->d[1]=p->mn[1]=p->mx[1]=now.d[1];}if(*p==now){p->sum++;p->cnt++;return;}if(now.d[D]<p->d[D])insert(p->ch[0],D^1);elseinsert(p->ch[1],D^1);update(p);if(!balance(p))rbt=&p,rbd=D;
}
void rebuild(node *&rt,bool f){vcnt=v;travel(rt);rt=0;rebuild(rt,1,vcnt-v,f);
}
inline void insert(node *&rt){rbt=0;insert(rt,0);if(rbt)rebuild(*rbt,rbd);
}
int get_sum(node *p,int x1,int y1,int x2,int y2){if(!p)return 0;if(in(x1,y1,x2,y2,p->mn[0],p->mn[1],p->mx[0],p->mx[1]))return p->sum;if(out(x1,y1,x2,y2,p->mn[0],p->mn[1],p->mx[0],p->mx[1]))return 0;return get_sum(p->ch[0],x1,y1,x2,y2)+get_sum(p->ch[1],x1,y1,x2,y2)+p->cnt*in(x1,y1,x2,y2,p->d[0],p->d[1],p->d[0],p->d[1]);
}
}
int x[MAXN+10],y[MAXN+10],val[MAXN+10];
namespace SegmentTree{
struct node{K_DTree::node *root;node *ch[2];
}tree[MAXN*20+10],*tcnt=tree,*nil=tree,*root=nil;
inline void init(){nil->ch[0]=nil->ch[1]=nil;
}
void insert(node *&p,int l,int r,int pos){if(p==nil){p=++tcnt;p->ch[0]=p->ch[1]=nil;}K_DTree::insert(p->root);if(l==r)return;int mid=(l+r)>>1;if(pos<=mid)insert(p->ch[0],l,mid,pos);elseinsert(p->ch[1],mid+1,r,pos);
}
int Query(node *p,int l,int r,int x1,int y1,int x2,int y2,int k){if(l==r)return l;int mid=(l+r)>>1,t;if((t=K_DTree::get_sum(p->ch[1]->root,x1,y1,x2,y2))>=k)return Query(p->ch[1],mid+1,r,x1,y1,x2,y2,k);return Query(p->ch[0],l,mid,x1,y1,x2,y2,k-t);
}
}
using namespace SegmentTree;
int main()
{init();Read(n),Read(Q);int x,y,v,x1,y1,p;while(Q--){Read(p);if(p==1){Read(x),Read(y),Read(v);x^=ans,y^=ans,v^=ans;K_DTree::now=K_DTree::node(x,y);insert(root,1,MAXV,v);}else{Read(x),Read(y),Read(x1),Read(y1),Read(v);x^=ans,y^=ans,x1^=ans,y1^=ans,v^=ans;if(K_DTree::get_sum(root->root,x,y,x1,y1)<v)puts("NAIVE!ORZzyz."),ans=0;elseprintf("%d\n",ans=Query(root,1,MAXV,x,y,x1,y1,v));}}
}

【线段树套KD树】[BZOJ4605]崂山白花蛇草水相关推荐

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

    Description Q次操作,要求资瓷 在(x,y)处放一个数字x 查询(x1,y1)到(x2,y2)矩形内第k大 Solution 非常裸的权值线段树套kd树,为了保证复杂度可以定期重构也可以平 ...

  2. bzoj4605: 崂山白花蛇草水 权值线段树套KDtree

    bzoj4605: 崂山白花蛇草水 链接 bzoj loj 思路 强制在线,那就权值线段树套KDtree好了,没啥好讲的. KDtree要加平衡因子来重构.另外,那水真难喝. 错误 树套树一边写过了, ...

  3. bzoj4605: 崂山白花蛇草水 //替罪羊式重构k-d树

    bzoj4605: 崂山白花蛇草水 题意 Q(<=100000)次操作,支持: 在二维平面上插入一个坐标(x,y)(x,y<=500000),点权为v(<=1e9)的点: 查询矩形区 ...

  4. [bzoj4605]崂山白花蛇草水 k-d tree 带替罪羊重构

    4605: 崂山白花蛇草水 Time Limit: 80 Sec  Memory Limit: 512 MB [Submit][Status][Discuss] Description 神犇Aleph ...

  5. [BZOJ4605]崂山白花蛇草水(主席树套kd-tree)

    题意:两种操作,在二维平面插入一个点及其权值,查询矩形区间第k大,强制在线. 之前考试考过一个矩形区间第k大的题..当时想了各种树套树套树,算了算复杂度都没有暴力快..后来憋了个kd-tree套主席树 ...

  6. bzoj4605 崂山白花蛇草水(动态开点线段树逃替罪羊重构K-D tree)

    首先我们发现它是一个三维的问题而且还强制在线 囧 我们可以考虑在外面来一个权值线段树,然后每次查询时在线段树二分即可,这样我们每个节点再套一棵K-D tree,用来查询有多少个点被框住了,然后因为是不 ...

  7. bzoj4605: 崂山白花蛇草水(权值线段树套k-dtree)

    题目 #include<bits/stdc++.h> using namespace std; #define mid (l+r>>1) const int N=100002, ...

  8. bzoj4605 崂山白花蛇草水

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4605 [题解] 序列上的第k大我们可以用线段树内套一个能查询序列某些地方有多少数的数据结构来 ...

  9. BZOJ4605 : 崂山白花蛇草水

    外层维护权值线段树,内层维护kd-tree. 修改的时候只往右儿子里插入,不平衡的时候替罪羊式重构. 查询的时候在外层线段树上走,在内层kd-tree上查询矩形内点数即可. 时间复杂度$O(q\log ...

最新文章

  1. bootstrapr表格父子框_使用Bootstrap Table建立父子表
  2. linux awk 用一个或多个空格做分隔符
  3. 内部结构透视XRAY
  4. Oracle语句连接查询
  5. P4168-[Violet]蒲公英【分块】
  6. 前端学习(2672):ts初步概念和功能实现
  7. POJ 1365 Prime Land
  8. php 获取顶级域名、一级域名
  9. 电子初学者需要掌握的几款电子设计软件
  10. Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0
  11. 小米平板2wifi驱动下载_小米平板2 win10驱动
  12. PHP操作MySQL数据库常用函数
  13. 中国大学mooc 慕课 管理信息系统(同济大学) 第八章 电子商务 第九章 信息系统规划 习题 测试答案
  14. 三菱FX3SA PLC连接威纶通MT6071iE触摸屏+计数器使用+循环执行N次+暂停+触摸屏软件安装包
  15. 华为荣耀7i刷linux,华为荣耀7i(ATH-AL00 全网通)ROOT教程,简单几步完成ROOT
  16. 天翎BPM流程引擎助力打造流程服务中台
  17. 校长办公室管理系统c语言,【锦城故事】学软硬结合理论做智慧超群系统是锦城电子的必经之路...
  18. 树莓派笔记12:通过SPI操作OLED显示屏
  19. 黄鱼车今后会少 下沙公交小巴向出租车转型
  20. 我们为什么要坚持写博客?

热门文章

  1. 牛客网SQL刷题问题汇总
  2. vba 将http.responseText返回的 unicode字符转换成中文
  3. 图片转换为矩阵/矩阵转换为图片
  4. cocos Creator android 上传图片与数据
  5. linux麒麟安装教程,优麒麟Ubuntu Kylin 18.04安装教程
  6. ultraiso制作u盘启动盘教程
  7. 联想小新一键恢复小孔_联想小新一键恢复小孔 联想小新笔记本怎么一键恢复...
  8. 京东金融-供应链金融业务介绍
  9. ios上架图片在线制作_iOS、Windows 值得下载的 12 个新 App
  10. java教程_java学习的秘籍