描述
Forsaken现在在一个三维空间中,空间中每个点都可以用 (x,y,z)(x,y,z)(x,y,z) 表示。突然,三维空间的主人出现了,如果Forsaken想要继续在三维空间中呆下去,他就必须回答三维空间主人的问题。
主人会在空间中坐标为 (x,y,z)(x,y,z)(x,y,z) 处加一点能量值,当他加了一定的次数之后,他会问Forsaken一个问题:如果坐标 (0,0,0)(0,0,0)(0,0,0) 为球心,那么至少需要多大的半径才能使得球内的能量值总和大于或者等于 kkk,在这里,半径为 000 也是可以的。这对于Forsaken来说实在是太难了,因此他把这个问题交给了你。
输入
第一行一个 nnn 表示操作的次数。
接下来每行首先一个整数 opopop 表示操作的种类。
如果 op=1op = 1op=1,接下来 333 个整数 x,y,zx,y,zx,y,z 表示能量值增加的坐标。
如果 op=2op = 2op=2,接下来一个整数 kkk 表示要求的能量值总和。
输出
对于每个 op=2op=2op=2 的操作,输出一个整数表示球的半径。(数据保证至少有一个 222 操作)
如果没有满足答案的半径,输出 −1-1−1 。
样例
输入
复制
2 1 1 1 1 2 1
输出
复制
2
提示
1≤n≤2e5
1≤op≤2
−1e5≤x,y,z≤1e5
0≤k≤2e5
树状数组+二分查找 (好久没写树状数组T-T)
#include<iostream>
#include<cmath>
#include<cstdio>
#define ll long long
#define maxn 200010
using namespace std;
int c[maxn];
int lowbit(int x) {
return x&(-x);
}
void add(int x) {
for(int i=x;i<maxn;i+=lowbit(i))
c[i]+=1;
}
int getsum(int x) {
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
ans += c[i];
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T,op,k,cnt=0;
double x,y,z;
ll num=-1;
cin >> T;
while(T--) {
cin >> op;
if(op==1) {
cin >> x >> y >> z;
cnt++;
double a = sqrt(x*x+y*y+z*z);
int aa = ceil(a);
add(aa);
}
else {
cin >> k;
if(k>cnt){
printf("-1\n");
continue;
}
//二分查找
int l=0,r=maxn,mid;
while(l<=r) {
mid = (l+r)/2;
if(getsum(mid)>=k)
r=mid-1;
else
l=mid+1;
}
printf("%d\n",l);
}
}
return 0;
}