4605: 崂山白花蛇草水
Time Limit: 80 Sec Memory Limit: 512 MB[ 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
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
HINT
Source
用权值线段树套kd树,kd树需用到替罪羊树的重构
初学kd树,学习Claris的代码,然后这个代码快如香港记者
然后flowerOJ上排第一(我当然不是yjq啦)
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 |
---|---|---|---|---|---|---|---|---|
#18327 | #99. 【BZOJ #4605】崂山白花蛇草水 | yjqqqaq | 100 | 2690ms | 27364kb | C++ | 3.5kb | 2017-08-21 20:13:50 |
#3278 | #99. 【BZOJ #4605】崂山白花蛇草水 | smallfat | 100 | 7771ms | 61976kb | C++ | 5.3kb | 2017-02-11 21:39:10 |
#3271 | #99. 【BZOJ #4605】崂山白花蛇草水 | abcd | 100 | 8099ms | 109108kb | C++ | 4.6kb | 2017-02-11 21:09:38 |
#4111 | #99. 【BZOJ #4605】崂山白花蛇草水 | std | 100 | 11307ms | 301792kb | C++ | 5.9kb | 2017-02-21 10:30:06 |
#2942 | #99. 【BZOJ #4605】崂山白花蛇草水 | chenxun | 100 | 12971ms | 301792kb | C++ | 5.9kb | 2017-02-06 17:26:00 |
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const double A = 0.8;
const int N = 100005, M = 1600005;
struct Node{ int l,r,mx[2],mn[2],d[2],siz; }t[M];
int n,k,X1,Y1,X2,Y2,ans,cmpp,op;
int tmp[N],need[N],deep,cnt,cur;
int T[M],l[M],r[M],tot=1;
bool cmp( int a, int b ){ return t[a].d[cmpp] < t[b].d[cmpp]; }
void umax( int &a, int b ){ if( a < b ) a = b; }
void umin( int &a, int b ){ if( a > b ) a = b; }
void update( int x ){
t[x].siz = t[t[x].l].siz + t[t[x].r].siz + 1;
if( t[x].l ){
umax( t[x].mx[0], t[t[x].l].mx[0] );
umax( t[x].mx[1], t[t[x].l].mx[1] );
umin( t[x].mn[0], t[t[x].l].mn[0] );
umin( t[x].mn[1], t[t[x].l].mn[1] );
} if( t[x].r ){
umax( t[x].mx[0], t[t[x].r].mx[0] );
umax( t[x].mx[1], t[t[x].r].mx[1] );
umin( t[x].mn[0], t[t[x].r].mn[0] );
umin( t[x].mn[1], t[t[x].r].mn[1] );
}
}
int build( int l, int r , int D ){
int mid = (l+r)>>1; cmpp = D;
nth_element( need+l+1, need+mid+1, need+r+1, cmp );
int x = need[mid];
t[x].mx[0] = t[x].mn[0] = t[x].d[0];
t[x].mx[1] = t[x].mn[1] = t[x].d[1];
t[x].l = ( l^mid ) ? build( l, mid-1, D^1 ) : 0;
t[x].r = ( r^mid ) ? build( mid+1, r, D^1 ) : 0;
update(x); return x;
}
void dfs( int x ){ if(x) need[++cnt] = x, dfs(t[x].l), dfs(t[x].r); }
void ins( int &root, int now ){
if(!root){ root = now; return; }
for( int D = deep = 0, x = root; ; D ^= 1 ){
tmp[++deep] = x;
umax( t[x].mx[0], t[now].mx[0] );
umax( t[x].mx[1], t[now].mx[1] );
umin( t[x].mn[0], t[now].mn[0] );
umin( t[x].mn[1], t[now].mn[1] );
t[x].siz++;
if( t[now].d[D] >= t[x].d[D] ){
if( !t[x].r ) { t[x].r = now; break; } else x = t[x].r;
}else{
if( !t[x].l ) { t[x].l = now; break; } else x = t[x].l;
}
}
tmp[++deep] = now;
if( deep < log(t[root].siz)/log(1/A)) return;
while( (double)t[t[now].l].siz < A*t[now].siz && (double)t[t[now].r].siz < A*t[now].siz ) now = tmp[--deep];
if(!now) return;
if( now == root ){
cnt = 0; dfs(root);
root = build( 1, cnt, 0 );
return ;
}
int y = tmp[--deep];
cnt = 0; dfs(now);
int k = build( 1, cnt, deep&1 );
if( t[y].l == now ) t[y].l = k; else t[y].r = k;
}
void ask( int x ){
if( !x || t[x].mx[0]<X1 || t[x].mn[0]>X2 || t[x].mx[1]<Y1 || t[x].mn[1]>Y2 || ans>=k ) return;
if( t[x].mn[0]>=X1 && t[x].mx[0]<=X2 && t[x].mn[1]>=Y1 && t[x].mx[1]<=Y2 ){ ans += t[x].siz; return;}
if( t[x].d[0]>=X1 && t[x].d[0]<=X2 && t[x].d[1]>=Y1 && t[x].d[1]<=Y2 ) ans++;
ask( t[x].l ); ask( t[x].r );
}
void add(){
int x = 1, a = 1, b = 1000000000, mid, flag = 1;
while(1){
if(flag){
cur++;
t[cur].mx[0] = t[cur].mn[0] = t[cur].d[0]=X1;
t[cur].mx[1] = t[cur].mn[1] = t[cur].d[1]=Y1;
t[cur].siz = 1; ins(T[x],cur);
}
if( a == b ) return;
mid = (a+b)>>1;
if( k <= mid ){
if( !l[x] ) l[x] = ++tot;
x = l[x], b = mid, flag = 0;
} else{
if( !r[x] ) r[x] = ++tot;
x = r[x], a = mid+1, flag = 1;
}
}
}
void query(){
ans = 0; ask(T[1]);
if( ans < k ){
puts("NAIVE!ORZzyz.");
ans = 0; return;
}
int x=1,a=1,b=1000000000,mid;
while( a < b ){
mid = (a+b)>>1;
ans = 0, ask( T[r[x]] );
if( ans >= k ) x = r[x], a = mid+1;
else k -= ans, x = l[x], b = mid;
}
printf("%d\n", ans=a);
}
int main(){
scanf("%d", &n); scanf("%d", &n);
while(n--){
scanf("%d%d%d", &op, &X1, &Y1);
if( op == 1 ){
scanf("%d", &k);
add();
} else{
scanf("%d%d%d", &X2, &Y2, &k);
query();
}
}
return 0;
}