bzoj4604 The kth maximum number && bzoj4605 崂山白花蛇草水
2016-12-18 23:36
363 查看
(bzoj4604为bzoj4605弱化版)
bzoj4605
【题意】
n次操作,操作有2种:
1.平面上单点点权赋值,保证每个点最多赋值1次。
2.查询矩形点权第k大。
强制在线。
【数据范围】
n<=100000,点权<=w=10^9
【思路】
若改成序列问题,可以使用权值线段树套线段树。
矩形问题可以考虑把内层线段树改为kd-tree。
故本题使用权值线段树套kd-tree。
kd-tree有两种重构方式:定时重构,替罪羊重构。我使用了替罪羊重构。
【时间复杂度】
O(n*sqrt(n)*log w)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
#define top 1000000000
#define alpha 0.77
using namespace std;
struct tt{int l, r, d[2], mx[2], mn[2], size;}t[N*35];
struct tt1{int l, r, root;}t1[N*35];
struct aa{int d[2], id;}a
;
int n, m, lastans, temp, l, x, y, z, x1, x2, y1, y2, D, l1, xx, fx, k, l2, rt;
inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
bool operator<(aa a, aa b){return a.d[D]<b.d[D];}
void update(int i){
for(int j=0; j<=1; j++){
t[i].mx[j]=t[i].mn[j]=t[i].d[j];
if(t[i].l){
t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);
}
if(t[i].r){
t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);
}
}
}
void kd_ins(int i, int x, int y, int now){
t[i].size++;
if(!now){
if(x<=t[i].d[0]){
if(!t[i].l){
l++; t[i].l=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].l, x, y, now^1);
}else{
if(!t[i].r){
l++; t[i].r=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].r, x, y, now^1);
}
}else{
if(y<=t[i].d[1]){
if(!t[i].l){
l++; t[i].l=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].l, x, y, now^1);
}else{
if(!t[i].r){
l++; t[i].r=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].r, x, y, now^1);
}
}
update(i);
if(max(t[t[i].l].size, t[t[i].r].size)>=t[i].size*alpha){xx=i; fx=0;}
if(xx&&t[i].l==xx)fx=i;
if(xx&&t[i].r==xx)fx=-i;
}
void kd_maketree(int L, int R, int now){
D=now; int mid=(L+R)>>1;
nth_element(a+L, a+mid, a+R+1);
rt=a[mid].id; t[rt].l=t[rt].r=0;
t[rt].d[0]=a[mid].d[0]; t[rt].d[1]=a[mid].d[1]; t[rt].size=R-L+1;
int p=rt;
if(L<mid){rt=0; kd_maketree(L, mid-1, now^1); t[p].l=rt;}
if(mid<R){rt=0; kd_maketree(mid+1, R, now^1); t[p].r=rt;}
update(p); rt=p;
}
void dfs(int i){
l2++; a[l2].d[0]=t[i].d[0]; a[l2].d[1]=t[i].d[1]; a[l2].id=i;
if(t[i].l)dfs(t[i].l);
if(t[i].r)dfs(t[i].r);
}
void sheep(int i){
l2=0; dfs(i);
rt=0; kd_maketree(1, l2, 0);
}
void dfs1(int i){
if(t[i].l)dfs1(t[i].l);
if(t[i].r)dfs1(t[i].r);
}
void ins1(int i, int L, int R, int x, int y, int z){
if(!t1[i].root){
l++; t1[i].root=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else{
xx=fx=0; kd_ins(t1[i].root, x, y, 0);
if(xx){
sheep(xx);
if(fx>0)t[fx].l=rt; if(fx<0)t[-fx].r=rt;
if(!fx)t1[i].root=rt;
}
}
if(L==R)return;
int mid=(L+R)>>1;
if(z<=mid){
if(!t1[i].l)t1[i].l=++l1;
ins1(t1[i].l, L, mid, x, y, z);
}else{
if(!t1[i].r)t1[i].r=++l1;
ins1(t1[i].r, mid+1, R, x, y, z);
}
}
int in(int x1, int x2, int y1, int y2, int X1, int X2, int Y1, int Y2){
return (X1<=x1)&&(x2<=X2)&&(Y1<=y1)&&(y2<=Y2);
}
int out(int x1, int x2, int y1, int y2, int X1, int X2, int Y1, int Y2){
return (X2<x1)||(x2<X1)||(Y2<y1)||(y2<Y1);
}
int csum(int i, int x1, int x2, int y1, int y2){
if(!i)return 0;
if(in(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1], x1, x2, y1, y2))return t[i].size;
if(out(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1], x1, x2, y1, y2))return 0;
int sum=0;
if(in(t[i].d[0], t[i].d[0], t[i].d[1], t[i].d[1], x1, x2, y1, y2))sum++;
sum+=csum(t[i].l, x1, x2, y1, y2)+csum(t[i].r, x1, x2, y1, y2); return sum;
}
int check1(int i, int L, int R, int x1, int x2, int y1, int y2, int k){
if(L==R)return L;
int sum, mid=(L+R)>>1;
if(!t1[i].r)sum=0; else sum=csum(t1[t1[i].r].root, x1, x2, y1, y2);
if(sum>=k)return check1(t1[i].r, mid+1, R, x1, x2, y1, y2, k);
else return check1(t1[i].l, L, mid, x1, x2, y1, y2, k-sum);
}
int main(){
m=read(); n=read(); lastans=0;
l=0; l1=1; t1[1].l=t1[1].r=0;
for(int i=1; i<=n; i++){
temp=read();
if(temp==1){
x=read()^lastans; y=read()^lastans; z=read()^lastans;
ins1(1, 1, top, x, y, z);
}else{
x1=read()^lastans; y1=read()^lastans; x2=read()^lastans; y2=read()^lastans; k=read()^lastans;
if(csum(t1[1].root, x1, x2, y1, y2)<k){lastans=0; printf("NAIVE!ORZzyz.\n");}
else{lastans=check1(1, 1, top, x1, x2, y1, y2, k); printf("%d\n", lastans);}
}
}
return 0;
}
bzoj4605
【题意】
n次操作,操作有2种:
1.平面上单点点权赋值,保证每个点最多赋值1次。
2.查询矩形点权第k大。
强制在线。
【数据范围】
n<=100000,点权<=w=10^9
【思路】
若改成序列问题,可以使用权值线段树套线段树。
矩形问题可以考虑把内层线段树改为kd-tree。
故本题使用权值线段树套kd-tree。
kd-tree有两种重构方式:定时重构,替罪羊重构。我使用了替罪羊重构。
【时间复杂度】
O(n*sqrt(n)*log w)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
#define top 1000000000
#define alpha 0.77
using namespace std;
struct tt{int l, r, d[2], mx[2], mn[2], size;}t[N*35];
struct tt1{int l, r, root;}t1[N*35];
struct aa{int d[2], id;}a
;
int n, m, lastans, temp, l, x, y, z, x1, x2, y1, y2, D, l1, xx, fx, k, l2, rt;
inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
bool operator<(aa a, aa b){return a.d[D]<b.d[D];}
void update(int i){
for(int j=0; j<=1; j++){
t[i].mx[j]=t[i].mn[j]=t[i].d[j];
if(t[i].l){
t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);
}
if(t[i].r){
t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);
}
}
}
void kd_ins(int i, int x, int y, int now){
t[i].size++;
if(!now){
if(x<=t[i].d[0]){
if(!t[i].l){
l++; t[i].l=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].l, x, y, now^1);
}else{
if(!t[i].r){
l++; t[i].r=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].r, x, y, now^1);
}
}else{
if(y<=t[i].d[1]){
if(!t[i].l){
l++; t[i].l=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].l, x, y, now^1);
}else{
if(!t[i].r){
l++; t[i].r=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else kd_ins(t[i].r, x, y, now^1);
}
}
update(i);
if(max(t[t[i].l].size, t[t[i].r].size)>=t[i].size*alpha){xx=i; fx=0;}
if(xx&&t[i].l==xx)fx=i;
if(xx&&t[i].r==xx)fx=-i;
}
void kd_maketree(int L, int R, int now){
D=now; int mid=(L+R)>>1;
nth_element(a+L, a+mid, a+R+1);
rt=a[mid].id; t[rt].l=t[rt].r=0;
t[rt].d[0]=a[mid].d[0]; t[rt].d[1]=a[mid].d[1]; t[rt].size=R-L+1;
int p=rt;
if(L<mid){rt=0; kd_maketree(L, mid-1, now^1); t[p].l=rt;}
if(mid<R){rt=0; kd_maketree(mid+1, R, now^1); t[p].r=rt;}
update(p); rt=p;
}
void dfs(int i){
l2++; a[l2].d[0]=t[i].d[0]; a[l2].d[1]=t[i].d[1]; a[l2].id=i;
if(t[i].l)dfs(t[i].l);
if(t[i].r)dfs(t[i].r);
}
void sheep(int i){
l2=0; dfs(i);
rt=0; kd_maketree(1, l2, 0);
}
void dfs1(int i){
if(t[i].l)dfs1(t[i].l);
if(t[i].r)dfs1(t[i].r);
}
void ins1(int i, int L, int R, int x, int y, int z){
if(!t1[i].root){
l++; t1[i].root=l;
t[l].l=t[l].r=0; t[l].d[0]=t[l].mx[0]=t[l].mn[0]=x;
t[l].d[1]=t[l].mx[1]=t[l].mn[1]=y; t[l].size=1;
}else{
xx=fx=0; kd_ins(t1[i].root, x, y, 0);
if(xx){
sheep(xx);
if(fx>0)t[fx].l=rt; if(fx<0)t[-fx].r=rt;
if(!fx)t1[i].root=rt;
}
}
if(L==R)return;
int mid=(L+R)>>1;
if(z<=mid){
if(!t1[i].l)t1[i].l=++l1;
ins1(t1[i].l, L, mid, x, y, z);
}else{
if(!t1[i].r)t1[i].r=++l1;
ins1(t1[i].r, mid+1, R, x, y, z);
}
}
int in(int x1, int x2, int y1, int y2, int X1, int X2, int Y1, int Y2){
return (X1<=x1)&&(x2<=X2)&&(Y1<=y1)&&(y2<=Y2);
}
int out(int x1, int x2, int y1, int y2, int X1, int X2, int Y1, int Y2){
return (X2<x1)||(x2<X1)||(Y2<y1)||(y2<Y1);
}
int csum(int i, int x1, int x2, int y1, int y2){
if(!i)return 0;
if(in(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1], x1, x2, y1, y2))return t[i].size;
if(out(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1], x1, x2, y1, y2))return 0;
int sum=0;
if(in(t[i].d[0], t[i].d[0], t[i].d[1], t[i].d[1], x1, x2, y1, y2))sum++;
sum+=csum(t[i].l, x1, x2, y1, y2)+csum(t[i].r, x1, x2, y1, y2); return sum;
}
int check1(int i, int L, int R, int x1, int x2, int y1, int y2, int k){
if(L==R)return L;
int sum, mid=(L+R)>>1;
if(!t1[i].r)sum=0; else sum=csum(t1[t1[i].r].root, x1, x2, y1, y2);
if(sum>=k)return check1(t1[i].r, mid+1, R, x1, x2, y1, y2, k);
else return check1(t1[i].l, L, mid, x1, x2, y1, y2, k-sum);
}
int main(){
m=read(); n=read(); lastans=0;
l=0; l1=1; t1[1].l=t1[1].r=0;
for(int i=1; i<=n; i++){
temp=read();
if(temp==1){
x=read()^lastans; y=read()^lastans; z=read()^lastans;
ins1(1, 1, top, x, y, z);
}else{
x1=read()^lastans; y1=read()^lastans; x2=read()^lastans; y2=read()^lastans; k=read()^lastans;
if(csum(t1[1].root, x1, x2, y1, y2)<k){lastans=0; printf("NAIVE!ORZzyz.\n");}
else{lastans=check1(1, 1, top, x1, x2, y1, y2, k); printf("%d\n", lastans);}
}
}
return 0;
}
相关文章推荐
- 【bzoj4604】The kth maximum number
- bzoj 4604: The kth maximum number
- BZOJ2456 Mode & zju2132 The Most Frequent Number(众数性质)
- <Socket> <BEA-000402> <There are: 5 active sockets, but the maximum number of socket reader threads
- HDU - 4006 The kth great number (set&数据结构)
- hdu 4006 The kth great number(STL 之set/priority_queue)
- 2011ACM大连网络赛 hdu 4006 The kth great number
- The terminal server has exceeded the maximum number of allowed connections
- hdoj 4006 The kth great number
- hdu 4006 The kth great number(使用优先队列)
- HDOJ-4006/(大连网赛1006)- The kth great number 剖析
- HDU 4006 The kth great number [2011 大连网络赛] [AVL树解法]
- POJ 2699 The Maximum Number of Strong Kings
- HDU--4006(The kth great number)
- HDU 4006 The kth great number
- hdu 4006 The kth great number 优先级队列
- The kth great number
- ERROR The terminal server has exceeded the maximum number of allowed connections
- The kth great number/hdoj 4006 2011 Regional Dalian Online priority queue
- The evil CMake -- Compile bug, missing ')', error line number