【BZOJ5328】【SDOI2018】—物理实验(扫描线+双指针)

传送门

题解:

#include<cstdio>
int main(){int t;cin>>t;while(t--)puts("nan");}

真的 A A 了……
有个 0 m s 0ms 就是我


说正解

先把导轨转到 x x 轴上
发现这时候 x x 长度相同的时候覆盖的长度和线段斜率是成正比的
于是我们可以把斜率当做价值

同时可以发现同一 x x 轴只需要维护 y y 最小的一段
可以用扫描线来维护所有线段,用 s e t set 维护一下就可以了

注意开 l o n g   d o u b l e long\ double

#include<bits/stdc++.h>
using namespace std;
#define double long double
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
	return res*f;
}
const int N=100005;
int n,m,q[N];
double x[N][2],y[N][2],sec[N],val[N],p[N],X0,Y0,X1,Y1,len;
inline bool comp(int a,int b){
	return ((a>0)?x[a][0]:x[-a][1])<((b>0)?x[b][0]:x[-b][1]);
}
struct line{
	int u;
	line(int _u=0):u(_u){}
	inline friend bool operator <(const line &a,const line &b){
		if(a.u==b.u)return false;
		double ya=(y[a.u][0]-y[a.u][1])/(x[a.u][0]-x[a.u][1])*(X0-x[a.u][0])+y[a.u][0];
		double yb=(y[b.u][0]-y[b.u][1])/(x[b.u][0]-x[b.u][1])*(X0-x[b.u][0])+y[b.u][0];
		return abs(ya)<abs(yb);
	}
};
set<line> up,down;
inline double P(double x){
	return x*x;
}
inline void solve(){
	double dx=X1-X0,dy=Y1-Y0,L=sqrt(P(dx)+P(dy)),si=dy/L,co=dx/L;
	for(int i=1;i<=n;i++){
        x[i][0]-=X0,x[i][1]-=X0,y[i][0]-=Y0,y[i][1]-=Y0;
        double t1,t2,t3,t4;
        t1=x[i][0]*co+y[i][0]*si,t2=y[i][0]*co-x[i][0]*si;
        t3=x[i][1]*co+y[i][1]*si,t4=y[i][1]*co-x[i][1]*si;
        x[i][0]=t1,y[i][0]=t2,x[i][1]=t3,y[i][1]=t4;
	}
	for(int i=1;i<=n;i++){
		if(x[i][0]>x[i][1])swap(x[i][0],x[i][1]),swap(y[i][0],y[i][1]);
		sec[i]=sqrt(P(x[i][0]-x[i][1])+P(y[i][0]-y[i][1]))/(x[i][1]-x[i][0]);
	}
	for(int i=1;i<=n;i++)q[++m]=i,q[++m]=-i;
	sort(q+1,q+m+1,comp);
	for(int i=1;i<=m;i++)val[i]=0;
	for(int i=1;i<=m;i++){
		if(q[i]>0){
			int u=q[i];X0=p[i]=x[u][0];
			if(!up.empty())val[i]+=sec[up.begin()->u];
			if(!down.empty())val[i]+=sec[down.begin()->u];
			if(y[u][0]>0)up.insert(line(u));
			else down.insert(line(u));
		}
		else{
			int u=-q[i];X0=p[i]=x[u][1];
			if(!up.empty())val[i]+=sec[up.begin()->u];
			if(!down.empty())val[i]+=sec[down.begin()->u];
			if(y[u][0]>0)up.erase(line(u));
			else down.erase(line(u));
		}
	}
	double res=0,ans=0,l=p[1]-len,r=p[1];int head=1,tail=2;
	while(tail<=m){
		double dl=p[head]-l,dr=p[tail]-r;
		if(dl>dr)res+=(val[tail]-val[head])*dr,tail++,l+=dr,r+=dr;
		else if(dl<dr)res+=(val[tail]-val[head])*dl,head++,l+=dl,r+=dl;
		else res+=(val[tail]-val[head])*dl,head++,tail++,l+=dl,r+=dl;
		ans=max(ans,res);
	}
	printf("%.13Lf\n",ans);
}
int main(){
	int T=read();
	while(T--){
		n=read(),m=0;
		for(int i=1;i<=n;i++){
			x[i][0]=read(),y[i][0]=read(),x[i][1]=read(),y[i][1]=read();
		}
		X0=read(),Y0=read(),X1=read(),Y1=read(),len=read();
		if(X0>X1)swap(X1,X0),swap(Y1,Y0);
		solve();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/88313670