列表

详情


NC53370. Forsaken的三维数点

描述

        Forsaken现在在一个三维空间中,空间中每个点都可以用表示。突然,三维空间的主人出现了,如果Forsaken想要继续在三维空间中呆下去,他就必须回答三维空间主人的问题。
        主人会在空间中坐标为处加一点能量值,当他加了一定的次数之后,他会问Forsaken一个问题:如果坐标为球心,那么至少需要多大的半径才能使得球内的能量值总和大于或者等于,在这里,半径为也是可以的。这对于Forsaken来说实在是太难了,因此他把这个问题交给了你。

输入描述

第一行一个表示操作的次数。
接下来每行首先一个整数表示操作的种类。
如果,接下来个整数表示能量值增加的坐标。
如果,接下来一个整数表示要求的能量值总和。

输出描述

对于每个的操作,输出一个整数表示球的半径。(数据保证至少有一个操作)
如果没有满足答案的半径,输出

示例1

输入:

2
1 1 1 1
2 1

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 635ms, 内存消耗: 5236K, 提交时间: 2019-10-28 19:33:14

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+100;
#define ll long  long 
ll c[N]; 
void add(int x)
{
	while(x<N)
	{
		c[x]++;
		x+=x&-x; 
	}
}
ll query(int x)
{
	ll ans=0;
	while(x)
	{
		ans+=c[x];
		x-=x&-x;
	}
	return ans;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int op;
		cin>>op;
		if(op==1)
		{
			double  x,y,z;
			cin>>x>>y>>z;
			add(ceil(sqrt(x*x+y*y+z*z))); 
		}
		else 
		{
			int k;
			cin>>k;
			int  l=0,r=2e5+10;
			while(l<r)
			{
				ll mid=l+r>>1;
				if(query(mid)>=k) r=mid;
				else l=mid+1;
			}
			if(l==2e5+10) cout<<-1<<endl;
			else cout<<l<<endl;
		}
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 656ms, 内存消耗: 5016K, 提交时间: 2019-10-28 13:11:56

 #include<iostream>
#include<cmath>
using namespace std;
long long n,x,y,z,p,k,c[300005],mid,ans;
void find(int x)
{

	for(;x<=300000;x+=(x&-x))
		c[x]++;
	return ;
}
int get(int x)
{
	int s=0;
	for(;x;x-=(x&-x))
		s+=c[x];
	return s;
}
int main()
{
	cin>>n;
	while(n--)
	{
		cin>>p;
		if(p==1)
		{
			cin>>x>>y>>z;
			find((int)(sqrt(x*x+y*y+z*z)+0.99999999));
		}
		else
		{
			cin>>k;
			int mid,l=0,r=300000;
			ans=-1;
			while(l<=r)
			{
				mid=(l+r)/2;
				if(get(mid)>=k)
					r=(ans=mid)-1;
				else
					l=mid+1;
			}
			cout<<ans<<"\n";
		}
	}
 } 

上一题