您的位置:首页 > 其它

【权值分块】bzoj3570 DZY Loves Physics I

2014-11-23 08:32 417 查看

以下部分来自:http://www.cnblogs.com/zhuohan123/p/3726306.html


此证明有误。

DZY系列。

这题首先是几个性质:

  1.所有球质量相同,碰撞直接交换速度,而球又没有编号,那么就可以直接视作两个球没有碰撞。

  2.所有的方向、初始位置都没有任何用处。

然后就是速度的问题了,根据题设

a⋅v=C

与这几个方程联立

a⋅v=C
s=v·t;
vt2=v02+2·a·s

解这个方程组,可以得到
vt=√(2·C·t+v02)

那么T时刻的速度vT的相对大小就直接由v0决定了,我们只需要找到第k小的v0,直接输出答案即可。

现在问题在于:支持插入,查询全局K大值。

平衡树显然可做,但是 权值线段树/权值树状数组 不是更快吗?

但是 权值分块 竟然更快呢?

可能是因为其极小的常数 以及 插入时O(1) 的复杂度吧。

#include<cstdio>
#include<cmath>
using namespace std;
#define max(a,b) (((a)>(b))?(a):(b))
int n,K,V,v[100001],m,b[100001],LIMIT,sz,sum,sumv[350],l[350],r[350],num[100001];
bool op;
double CONST,T;
inline int R(){
char c=0;int f=1,x;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0');
x*=f; return x;
}
void makeblock()
{
sz=sqrt(LIMIT); if(!sz) sz=1; r[0]=-1;
for(sum=1;sum*sz<LIMIT;sum++)
{
l[sum]=r[sum-1]+1;
r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
}
l[sum]=r[sum-1]+1;
r[sum]=LIMIT;
for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
}
void Insert(const int &x){b[x]++; sumv[num[x]]++;}
inline int Kth(const int &x)
{
int cnt=0;
for(int i=1;;i++)
{
cnt+=sumv[i];
if(cnt>=x)
{
cnt-=sumv[i];
for(int j=l[i];;j++)
{cnt+=b[j]; if(cnt>=x) return j;}
}
}
}
inline double sqr(const double &x){return x*x;}
int main()
{
n=R(); CONST=(double)R();
for(int i=1;i<=n;i++)
{
v[i]=R(); R(); R();
LIMIT=max(LIMIT,v[i]);
} makeblock(); m=R();
for(int i=1;i<=n;i++) Insert(v[i]);
for(int i=1;i<=m;i++)
{
op=R(); if(op)
{
T=(double)R(); K=R();
printf("%.3f\n",sqrt(2.0*CONST*T+sqr((double)Kth(K))));
}
else {V=R(); R(); R(); Insert(V);}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: