题目描述
Forsaken现在在一个三维空间中,空间中每个点都可以用(x,y,z)(x,y,z)表示。突然,三维空间的主人出现了,如果Forsaken想要继续在三维空间中呆下去,他就必须回答三维空间主人的问题。
主人会在空间中坐标为(x,y,z)(x,y,z)处加一点能量值,当他加了一定的次数之后,他会问Forsaken一个问题:如果坐标(0,0,0)(0,0,0)为球心,那么至少需要多大的半径才能使得球内的能量值总和大于或者等于kk,在这里,半径为00也是可以的。这对于Forsaken来说实在是太难了,因此他把这个问题交给了你。
输入描述:
第一行一个nn表示操作的次数。
接下来每行首先一个整数opop表示操作的种类。
如果op = 1op=1,接下来33个整数x,y,zx,y,z表示能量值增加的坐标。
如果op =2op=2,接下来一个整数kk表示要求的能量值总和。
输出描述:
对于每个op=2op=2的操作,输出一个整数表示球的半径。(数据保证至少有一个22操作)
如果没有满足答案的半径,输出-1−1。
示例1
输入
复制
2
1 1 1 1
2 1
输出
复制
2
备注:
1 \leq n \leq 2e51≤n≤2e5
1 \leq op \leq 21≤op≤2
-1e5 \leq x, y, z \leq 1e5−1e5≤x,y,z≤1e5
0\leq k \leq 2e50≤k≤2e5
比较简单,因为球覆盖的原因,我们可以用一个坐标表示三个坐标,然后就维护一下即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int n,m;
struct node{
int op,x;
}q[N];
struct seg{
int l,r,s;
}t[N<<2];
void build(int p,int l,int r){
t[p].l=l; t[p].r=r;
if(l==r) return ; int mid=l+r>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
}
void change(int p,int x){
if(t[p].l==t[p].r) return void(t[p].s++);
int mid=t[p].l+t[p].r>>1;
if(x<=mid) change(p<<1,x);
else change(p<<1|1,x);
t[p].s=t[p<<1].s+t[p<<1|1].s;
}
int ask(int p,int l,int r){
if(t[p].l==l&&t[p].r==r) return t[p].s;
int mid=t[p].l+t[p].r>>1;
if(r<=mid) return ask(p<<1,l,r);
else if(l>mid) return ask(p<<1|1,l,r);
else return ask(p<<1,l,mid)+ask(p<<1|1,mid+1,r);
}
int bsearch(int val){
int l=0,r=2e5+1;
if(val==0) return 0;
if(ask(1,1,1e6)<val) return -1;
while(l<r){
int mid=l+r>>1;
if(ask(1,1,mid)>=val) r=mid;
else l=mid+1;
}
return l-1;
}
signed main(){
build(1,1,1000000);
cin>>n;
for(int i=1;i<=n;i++){
scanf("%lld",&q[i].op);
if(q[i].op==1){
int x,y,z; scanf("%lld %lld %lld",&x,&y,&z); q[i].x=ceil(sqrt((double)1.0*x*x+y*y+z*z))+1;
}
else scanf("%lld",&q[i].x);
}
for(int i=1;i<=n;i++){
if(q[i].op==1) change(1,q[i].x);
else printf("%lld\n",bsearch(q[i].x));
}
return 0;
}