洛谷P4848 崂山白花蛇草水 权值线段树+KDtree
题目描述
神犇 \(Aleph\) 在 \(SDOI\ Round2\) 前立了一个 \(flag\):如果进了省队,就现场直播喝崂山白花蛇草水。凭借着神犇 \(Aleph\) 的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了。蒟蒻 \(Bob\) 特地为他准备了 \(999,999,999,999,999,999\) 瓶崂山白花蛇草水,想要灌神犇 \(Aleph\)。神犇 \(Aleph\) 求(跪着的)蒟蒻 \(Bob\) 不要灌他,由于神犇 \(Aleph\) 是神犇,蒟蒻 \(Bob\) 最终答应了他的请求,但蒟蒻 \(Bob\) 决定将计就计,也让神犇 $Aleph4 回答一些问题。
具体说来,蒟蒻 \(Bob\) 会在一个宽敞的广场上放置一些崂山白花蛇草水(可视为二维平面上的一些整点),然后询问神犇 \(Aleph\) 在矩形区域 \(x_1\le x\le x_2,y_1\le y\le y_2\) 中,崂山白花蛇草水瓶数第 \(k\) 多的是多少。为了避免麻烦,蒟蒻 \(Bob\) 不会在同一个位置放置两次或两次以上的崂山白花蛇草水,但蒟蒻 \(Bob\) 想为难一下神犇 \(Aleph\),希望他能在每次询问时立刻回 答出答案。
神犇 \(Aleph\) 不屑于做这种问题,所以把这个问题交给了你。
输入格式
输入的第一行为两个正整数 \(n\),\(q\),表示横纵坐标的范围和蒟蒻 \(Bob\) 的操作次数(包括放置次数和询问次数)。
接下来 \(q\) 行,每行代表蒟蒻 \(Bob\) 的一个操作,操作格式如下:
首先第一个数字 \(\mathrm{type}\),表示操作种类。\(\mathrm{type}=1\) 表示放置,\(\mathrm{type}=2\) 表示询问。
若 \(\mathrm{type}=1\),接下来会有三个正整数 \(x, y, v\),表示在坐标整点 \((x, y)\) 放置v瓶崂山白花蛇草水。
若 \(\mathrm{type}=2\),接下来会有五个正整数 \(x_1, y_1, x_2, y_2, k\),表示询问矩形区域 \(x_1\le x\le x_2,y_1\le y\le y_2\) 中,崂山白花蛇草水瓶数第 \(k\) 多的是多少。
为了体现程序的在线性,你需要将每次读入的数据(除了 \(\mathrm{type}\) 值)都异或 \(\mathrm{lastans}\),其中 \(\mathrm{lastans}\) 表示上次询问的答 案。如果上次询问的答案为 \(NAIVE!ORZzyz\).(见样例输出),则将 \(\mathrm{lastans}\) 置为 \(0\)。初始时的 \(\mathrm{lastans}\) 为 \(0\)。 初始时平面上不存在崂山白花蛇草水。
输出格式
对于每个 \(\mathrm{type}=2\) 的操作,一行输出崂山白花蛇草水瓶数第 \(k\) 多的是多少。若不存在第 \(k\) 多的瓶数, 请输出 \(NAIVE!ORZzyz.\)。
输入输出样例
输入 #1
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
NAIVE!ORZzyz.
NAIVE!ORZzyz.
3
说明/提示
对于所有数据,\(n\le500000\),\(q\le100000\),\(1\le x, y\le n\),\(1\le v\le 10^9\),\(1\le x_1\le x_2\le n\),\(1\le y_1\le y_2\le n\),\(1\le k\le q\)。
分析
在给定的矩形内查询第 \(k\) 大的权值
动态加点,强制在线
这种题一个非常好想的做法就是开一个小根堆维护最大的 \(k\) 个元素
每次只更新队首的元素
这种做法在 \(k\) 比较小的情况下是没有问题的
然而这道题 \(k\) 的范围达到了 \(10^5\) ,显然会 \(T\) 到飞起
所以我们需要另一种能够支持查询区间 \(k\) 大值的数据结构,比如权值线段树
权值线段树的每个节点上都维护一棵 \(kdtree\)
\(kdtree\) 中存储权值为当前节点下标的所有点的坐标
因为要动态加点,为了防止二叉树退化成一条链,需要借鉴替罪羊的思想暴力重构
要注意的是,暴力重构时,不能这样写
void dfs(rg int da){
sta[++tp]=da;
jl[tp]=ktr[da];
if(ktr[da].lc) dfs(ktr[da].lc);
if(ktr[da].rc) dfs(ktr[da].rc);
}
而要这样写
void dfs(rg int da){
sta[++tp]=da;
jl[tp].d[0]=ktr[da].d[0];
jl[tp].d[1]=ktr[da].d[1];
if(ktr[da].lc) dfs(ktr[da].lc);
if(ktr[da].rc) dfs(ktr[da].rc);
}
因为你直接继承 \(min\) 和 \(max\) 会对之后节点的更新造成影响
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e6+5,INF=1e9;
const double alpha=0.75;
inline int Max(rg int aa,rg int bb){
return aa>bb?aa:bb;
}
inline int Min(rg int aa,rg int bb){
return aa<bb?aa:bb;
}
int orz,kcnt,sta[maxn],tp;
struct kdt{
int lc,rc,mn[2],mx[2],d[2],siz;
friend bool operator <(const kdt& A,const kdt& B){
return A.d[orz]<B.d[orz];
}
}ktr[maxn*5],jl[maxn*5];
inline int newnode(){
if(tp) return sta[tp--];
else return ++kcnt;
}
void push_up(rg int da){
rg int lc=ktr[da].lc,rc=ktr[da].rc;
for(rg int i=0;i<2;i++){
ktr[da].mn[i]=ktr[da].mx[i]=ktr[da].d[i];
if(lc){
ktr[da].mn[i]=Min(ktr[da].mn[i],ktr[lc].mn[i]);
ktr[da].mx[i]=Max(ktr[da].mx[i],ktr[lc].mx[i]);
}
if(rc){
ktr[da].mn[i]=Min(ktr[da].mn[i],ktr[rc].mn[i]);
ktr[da].mx[i]=Max(ktr[da].mx[i],ktr[rc].mx[i]);
}
}
ktr[da].siz=ktr[lc].siz+ktr[rc].siz+1;
}
int build(rg int l,rg int r,rg int pl){
orz=pl;
rg int da=newnode(),mids=(l+r)>>1;
std::nth_element(jl+l,jl+mids,jl+r+1);
ktr[da]=jl[mids];
if(l<mids) ktr[da].lc=build(l,mids-1,!pl);
if(mids<r) ktr[da].rc=build(mids+1,r,!pl);
push_up(da);
return da;
}
void dfs(rg int da){
sta[++tp]=da;
jl[tp].d[0]=ktr[da].d[0];
jl[tp].d[1]=ktr[da].d[1];
if(ktr[da].lc) dfs(ktr[da].lc);
if(ktr[da].rc) dfs(ktr[da].rc);
}
void check(rg int &da,rg int pl){
rg int lc=ktr[da].lc,rc=ktr[da].rc;
if(ktr[lc].siz>ktr[da].siz*alpha || ktr[rc].siz>ktr[da].siz*alpha){
tp=0;
dfs(da);
da=build(1,tp,pl);
}
}
int ad(rg int da,rg int nx,rg int ny,rg int pl){
if(!da){
da=newnode();
ktr[da].mn[0]=ktr[da].mx[0]=ktr[da].d[0]=nx;
ktr[da].mn[1]=ktr[da].mx[1]=ktr[da].d[1]=ny;
ktr[da].siz=1;
return da;
}
if(pl==0){
if(nx<ktr[da].d[0]) ktr[da].lc=ad(ktr[da].lc,nx,ny,!pl);
else ktr[da].rc=ad(ktr[da].rc,nx,ny,!pl);
} else {
if(ny<ktr[da].d[1]) ktr[da].lc=ad(ktr[da].lc,nx,ny,!pl);
else ktr[da].rc=ad(ktr[da].rc,nx,ny,!pl);
}
push_up(da);
if(ktr[da].siz>6) check(da,pl);
return da;
}
int cx(rg int da,rg int a1,rg int a2,rg int b1,rg int b2){
if(!da) return 0;
if(ktr[da].mx[0]<a1 || ktr[da].mn[0]>a2 || ktr[da].mx[1]<b1 || ktr[da].mn[1]>b2) return 0;
if(ktr[da].mx[0]<=a2 && ktr[da].mn[0]>=a1 && ktr[da].mx[1]<=b2 && ktr[da].mn[1]>=b1){
return ktr[da].siz;
}
rg int nans=0;
if(ktr[da].d[0]<=a2 && ktr[da].d[0]>=a1 && ktr[da].d[1]<=b2 && ktr[da].d[1]>=b1) nans++;
nans+=cx(ktr[da].lc,a1,a2,b1,b2);
nans+=cx(ktr[da].rc,a1,a2,b1,b2);
return nans;
}
struct trr{
int lc,rc;
}tr[maxn*10];
int rk[maxn],cnt,rt;
int xg(rg int da,rg int l,rg int r,rg int wz,rg int nx,rg int ny){
if(!da) da=++cnt;
rg int mids=(l+r)>>1;
rk[da]=ad(rk[da],nx,ny,0);
if(l==r) return da;
if(wz<=mids) tr[da].lc=xg(tr[da].lc,l,mids,wz,nx,ny);
else tr[da].rc=xg(tr[da].rc,mids+1,r,wz,nx,ny);
return da;
}
int trcx(rg int da,rg int l,rg int r,rg int kth,rg int a1,rg int a2,rg int b1,rg int b2){
if(l==r) return l;
rg int nans=cx(rk[tr[da].rc],a1,a2,b1,b2),mids=(l+r)>>1;
if(nans>=kth) return trcx(tr[da].rc,mids+1,r,kth,a1,a2,b1,b2);
else return trcx(tr[da].lc,l,mids,kth-nans,a1,a2,b1,b2);
}
int n,q,latans;
int main(){
n=read(),q=read();
rg int aa,bb,cc,dd,ee,ff;
for(rg int i=1;i<=q;i++){
aa=read(),bb=read(),cc=read(),dd=read();
bb^=latans,cc^=latans,dd^=latans;
if(aa==1){
rt=xg(rt,1,INF,dd,bb,cc);
} else {
ee=read(),ff=read();
ee^=latans,ff^=latans;
if(cx(rk[rt],bb,dd,cc,ee)<ff){
printf("NAIVE!ORZzyz.\n");
latans=0;
} else {
printf("%d\n",latans=trcx(rt,1,INF,ff,bb,dd,cc,ee));
}
}
}
return 0;
}
洛谷P4848 崂山白花蛇草水 权值线段树+KDtree的更多相关文章
- 【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree
[BZOJ4605]崂山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了 ...
- 【bzoj4605】崂山白花蛇草水 权值线段树套KD-tree
题目描述 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob ...
- 崂山白花蛇草水 权值线段树套KDtree
Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实 力,他轻松地进了山东省省队,现在便是他履行诺言的时 ...
- bzoj4605: 崂山白花蛇草水 权值线段树套KDtree
bzoj4605: 崂山白花蛇草水 链接 bzoj loj 思路 强制在线,那就权值线段树套KDtree好了,没啥好讲的. KDtree要加平衡因子来重构.另外,那水真难喝. 错误 树套树一边写过了, ...
- 洛谷P3586 [POI2015]LOG(贪心 权值线段树)
题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被 ...
- BZOJ 4605 崂山白花蛇草水(权值线段树+KD树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4605 [题目大意] 操作 1 x y k 表示在点(x,y)上放置k个物品, 操作 2 ...
- luogu P4848 崂山白花蛇草水
https://www.luogu.org/problemnew/show/P4848 我的数据结构大概已经废了. 外层权值线段树内层kdtree,外层线段树上二分答案. 码数据结构一时爽,码完deb ...
- 洛谷P1908 逆序对 [权值线段树]
题目传送门 逆序对 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的 ...
- P4848 崂山白花蛇草水
题意:支持修改的矩形第 \(k\) 大. 题解:动态开点权值线段树 套 Kd-tree. 然后也没什么难的但就是写不对...调了两天才调出来然后发现跑的巨慢,于是又%了一发Claris'题解,跑的真快 ...
随机推荐
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的windowIcon属性
windowIcon对象为部件对象的属性,但只有窗口对象有效,其他派生对象如pushButtong对象无效. 在windowIcon对象上有如下子属性设置: 这几个子属性实际上是QIcon类中继承的. ...
- PyQt(Python+Qt)学习随笔:窗口对象尺寸调整相关的函数resize、showMaximized、showNormal、showMinimized
resize(width,height) resize可以直接调整窗口的尺寸,调整效果类似于鼠标直接拉伸或缩小窗口,但窗口大小的最大值.最小值受窗口的sizePolicy.sizeHint.minim ...
- Node.js 应用---定时给自己发送邮件
参照传智播客的视频所写代码. js代码: //引用superagent包,用于服务器发送http请求 const request = require('superagent'); //导入cheeri ...
- CTF SHOW WEB_AK赛
CTF SHOW平台的WEB AK赛: 签到_观己 <?php if(isset($_GET['file'])){ $file = $_GET['file']; if(preg_match( ...
- Android夜神模拟器
夜神安卓模拟器 NOX,是一个可以让手机应用程序运行在电脑上的软件,也是电脑玩手游的新一代神器, 与传统安卓模拟器相比,基于基于Android5.1.1,兼容X86/AMD,在性能.稳定性.兼容性等方 ...
- 【面试题】GC Root都有哪些?
那天去面试,面试官问我JVM垃圾回收,我是有备而来,上来就是一个可达性分析算法,然后就是一个复制算法,标记-清理,标记-整理,以及几个常见的垃圾回收器 详情见:https://www.cnblogs. ...
- Windows下MySQL无法启动万能解决方案
MySQL启动报错 window10上安装了MySQL之前使用都是执行net start mysql 启动,执行net stop mysql关闭. 某天开始启动报错"MySQL 服务无法启动 ...
- vue项目中扫码枪收款
扫码枪会将扫到的数据带入到获取焦点的输入框中,并且触发输入框的enter回车事件 1.页面上要有一个输入框,并且是获取焦点状态,当然它是隐藏的看不到,我是把宽高设置为0,然后加上回车事件. ...
- 开源性能监控分析工具glowroot
最近在做java性能瓶颈定位分析工具的研究,发现glowroot工具是一款相当不错的APM工具(Wonderful tool),架构简洁,部署简单,上手容易. 经过亲身搭建体验,总结了产品的架构,工具 ...
- ASP数据库连接方法语法总结
经常使用到有关数据库的操作.包括连接代码,SQL命令等等,又不曾刻意去记忆它们(我本人是不愿意去记这东东),所以常常在用到的时候又去查书本,翻来翻去.一些比较少用的数据库还不一定能顺利找到,所以现在把 ...