您的位置:首页 > 其它

【JZOJ 4783】 Osu

2016-09-18 19:21 399 查看

Description





Analysis

二分模型很显然,但是具体怎么二分

%%%CTY实数二分碾过

其实正解是把两两点对距离排序在这个数组里二分,这样个数是O(n^2)的。

判定的话可以用一个简单的n^2dp解决

这样大体框架就没了,但是此题巨猥琐卡常数

所以呢,卡常+一堆优化

Code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef double db;
const int N=2010,M=N*N;
int n,m,k,f
,g
;
char ch;
struct node
{
int t,x,y;
}a
;
struct lyd
{
int a,b,c;
db s;
}dis[M],cty;
int read()
{
int t=0,p=1;
for(ch=getchar();ch<'0' || ch>'9';ch=getchar())
if(ch=='-') p=-1;
for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';
return t*p;
}
int sqr(int x){return x*x;}
int gcd(int x,int y)
{
if(x%y==0) return y;
else return gcd(y,x%y);
}
db dist(node a,node b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
void getdis(node a,node b)
{
int d=sqr(a.x-b.x)+sqr(a.y-b.y),t=b.t-a.t;
dis[++m].s=sqrt(d)/t,dis[m].a=1,dis[m].b=d,dis[m].c=t;
}
bool biger(db a,db b)
{
return (a-b<=1e-9 && b-a<=1e-9) || a>=b;
}
bool check(db s)
{
memset(f,0,sizeof(f));
int mx=0;
fo(i,1,n)
{
g[i]=g[i-1];
for(int j=i-1;j>=0;j--)
{
if(biger(s*(a[i].t-a[j].t),dist(a[j],a[i])))
if(f[j]+1>f[i]) f[i]=f[j]+1;
if(f[i]>g[j]+1) break;
}
if(f[i]>mx) mx=f[i];
if(f[i]>g[i]) g[i]=f[i];
}
if(mx>=k) return 1;
return 0;
}
void qsort(int i,int j)
{
int l=i,r=j;
db mid=dis[(i+j)>>1].s;
do
{
while(dis[i].s<mid) i++;
while(dis[j].s>mid) j--;
if(i<=j)
{
cty=dis[i];
dis[i]=dis[j];
dis[j]=cty;
i++,j--;
}
}
while(i<=j);
if(i<r) qsort(i,r);
if(l<j) qsort(l,j);
}
int main()
{
n=read(),k=read();
fo(i,1,n) a[i].t=read(),a[i].x=read(),a[i].y=read();
fo(i,1,n-1)
fo(j,i+1,n) getdis(a[i],a[j]);
qsort(1,m);
int l=1,r=m,mid;
while(l<r)
{
mid=(l+r)>>1;
if(check(dis[mid].s)) r=mid;
else l=mid+1;
}
for(int i=2;i*i<=dis[l].b;i++)
while(dis[l].b%(i*i)==0) dis[l].a*=i,dis[l].b/=i*i;
int t=gcd(dis[l].a,dis[l].c);
dis[l].a/=t,dis[l].c/=t;
printf("%d %d %d",dis[l].a,dis[l].b,dis[l].c);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: