NC53370Forsaken的三維數點
阿新 • • 發佈:2020-07-21
連結:https://ac.nowcoder.com/acm/problem/53370
來源:牛客網
題目描述
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。
思路
題目要求是求空間內球體的半徑多長時可以符合能量值大於等於k的情況,這個時候由於輸出的是一個整數,也就是這個整數是來表示半徑的。
再加上題目求的是區間和,所以考慮樹狀陣列。
接下來為了使能夠構成樹狀陣列,在半徑可以回答0的情況時是無法構成樹狀陣列的,因為樹狀陣列是到達1處時求和就結束的。
所以我們給求出的每個半徑都+1就可以構成樹狀陣列了。
然後二分判斷情況。
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define DOF 0x7f7f7f7f #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define debug(case,x); cout<<case<<" : "<<x<<endl; #define open freopen("ii.txt","r",stdin) #define close freopen("oo.txt","w",stdout) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pb push_back using namespace std; #define int long long const int maxn=1e6+10; int k; int d[maxn]; inline int lowbit(int x){return -x&x;} void add(int x,int y){ while(x<=200000){ d[x]+=y;x+=lowbit(x); } } int get_sum(int x){ int ans=0; while(x){ ans+=d[x];x-=lowbit(x); } return ans; } signed main(){ int m; cin>>m; while(m--){ int x,y,z,op; cin>>op; if(op==1){ cin>>x>>y>>z; add(ceil(sqrt(x*x+y*y+z*z))+1,1); }else{ cin>>k; if(get_sum(200000)<k){ cout<<-1<<endl; }else{ int l=1,r=200000,mid; while(l<=r){ mid=l+r>>1; if(get_sum(mid)>=k){ r=mid-1; }else l=mid+1; } cout<<r<<endl; } } } }