以下部分来自: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) 的复杂度吧。
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 #define max(a,b) (((a)>(b))?(a):(b)) 5 int n,K,V,v[100001],m,b[100001],LIMIT,sz,sum,sumv[350],l[350],r[350],num[100001]; 6 bool op; 7 double CONST,T; 8 inline int R(){ 9 char c=0;int f=1,x; 10 for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1; 11 for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0'); 12 x*=f; return x; 13 } 14 void makeblock() 15 { 16 sz=sqrt(LIMIT); if(!sz) sz=1; r[0]=-1; 17 for(sum=1;sum*sz<LIMIT;sum++) 18 { 19 l[sum]=r[sum-1]+1; 20 r[sum]=sum*sz; 21 for(int i=l[sum];i<=r[sum];i++) num[i]=sum; 22 } 23 l[sum]=r[sum-1]+1; 24 r[sum]=LIMIT; 25 for(int i=l[sum];i<=r[sum];i++) num[i]=sum; 26 } 27 void Insert(const int &x){b[x]++; sumv[num[x]]++;} 28 inline int Kth(const int &x) 29 { 30 int cnt=0; 31 for(int i=1;;i++) 32 { 33 cnt+=sumv[i]; 34 if(cnt>=x) 35 { 36 cnt-=sumv[i]; 37 for(int j=l[i];;j++) 38 {cnt+=b[j]; if(cnt>=x) return j;} 39 } 40 } 41 } 42 inline double sqr(const double &x){return x*x;} 43 int main() 44 { 45 n=R(); CONST=(double)R(); 46 for(int i=1;i<=n;i++) 47 { 48 v[i]=R(); R(); R(); 49 LIMIT=max(LIMIT,v[i]); 50 } makeblock(); m=R(); 51 for(int i=1;i<=n;i++) Insert(v[i]); 52 for(int i=1;i<=m;i++) 53 { 54 op=R(); if(op) 55 { 56 T=(double)R(); K=R(); 57 printf("%.3f ",sqrt(2.0*CONST*T+sqr((double)Kth(K)))); 58 } 59 else {V=R(); R(); R(); Insert(V);} 60 } 61 return 0; 62 }