zoukankan      html  css  js  c++  java
  • [SDOI2018]物理实验 set,扫描线,旋转坐标系

    [SDOI2018]物理实验 set,扫描线,旋转坐标系

    链接

    [loj](#2561. 「SDOI2018」物理实验)

    思路

    先将导轨移到原点,然后旋转坐标系,参考博客
    然后分线段,每段的贡献(三角函数值)求出来,用自己喜欢的平衡树,我选set。
    显然答案的一端是小线段的端点。
    然后扫描线求出最大的ans。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e5+7;
    int n,op[N];
    long double X[N][2],Y[N][2],x[2],y[2],nx,csc[N],val[N<<1],pos[N<<1],L;
    bool cmp(int x,int y) {
    	return ((x>0) ? X[x][0] : X[-x][1])  < ((y>0) ? X[y][0] : X[-y][1]);
    }
    struct node {
    	int u;
    	node(int x=0) {u=x;}
    	bool operator < (const node &b) const {
    		if(u==b.u) return 0;
    		long double tmp1=(Y[u][1]-Y[u][0])/(X[u][1]-X[u][0])*(nx-X[u][0])+Y[u][0];
    		long double tmp2=(Y[b.u][1]-Y[b.u][0])/(X[b.u][1]-X[b.u][0])*(nx-X[b.u][0])+Y[b.u][0];
    		return ((tmp1>0) ? tmp1 : -tmp1) < ((tmp2>0) ? tmp2 : -tmp2);
    	}
    };
    set<node> up,down;
    void solve() {
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%Lf%Lf%Lf%Lf",&X[i][0],&Y[i][0],&X[i][1],&Y[i][1]);
    	scanf("%Lf%Lf%Lf%Lf%Lf",&x[0],&y[0],&x[1],&y[1],&L);
    	long double dx=x[0]-x[1],dy=y[0]-y[1];
    	for(int i=1;i<=n;++i) csc[i]=sqrt((X[i][0]-X[i][1])*(X[i][0]-X[i][1])+(Y[i][0]-Y[i][1])*(Y[i][0]-Y[i][1]));
    	long double dw=(x[0]!=x[1]) ? y[1]-(dy/dx)*x[1] : 0;
    	long double dis=sqrt(dx*dx+dy*dy);
    	for(int i=1;i<=n;++i) Y[i][0]-=dw,Y[i][1]-=dw;
    	dx/=dis,dy/=dis;
    	for(int i=1;i<=n;++i) {
    		long double tmp1,tmp2,tmp3,tmp4;
    		tmp1=dx*X[i][0]+dy*Y[i][0],
    		tmp2=dx*X[i][1]+dy*Y[i][1],
    		tmp3=dx*Y[i][0]-dy*X[i][0],
    		tmp4=dx*Y[i][1]-dy*X[i][1];
    		X[i][0]=tmp1,
    		X[i][1]=tmp2,
    		Y[i][0]=tmp3,
    		Y[i][1]=tmp4;
    		if(X[i][0]>X[i][1]) {  
    			swap(X[i][0],X[i][1]);
    			swap(Y[i][0],Y[i][1]);
    		}
    		csc[i]/=(X[i][1]-X[i][0]);
    		op[i]=-i,op[i+n]=i;
    	}
    	sort(op+1,op+1+2*n,cmp);
    	for(int i=1;i<=2*n;++i) {
    		if(op[i]>0) {
    			nx=pos[i]=X[op[i]][0];
    			(Y[op[i]][0]>0 ? up : down).insert(node(op[i]));
    			if(!up.empty()) val[i]+=csc[up.begin()->u];
    			if(!down.empty()) val[i]+=csc[down.begin()->u];
    		} else {
    			nx=pos[i]=X[-op[i]][1];
    			(Y[-op[i]][1]>0 ? up : down).erase(node(-op[i]));
    			if(!up.empty()) val[i]+=csc[up.begin()->u];
    			if(!down.empty()) val[i]+=csc[down.begin()->u];
    		}		
    	}
    	for(int i=2*n;i>=1;--i) val[i]=val[i-1];
    	long double attack=0,ll=pos[1]-L,rr=pos[1],ans=0;
    	int pl=1,pr=2;
    	while(pr<=2*n) {
    		long double dl=pos[pl]-ll;
    		long double dr=pos[pr]-rr;
    		if(dl>dr) {
    			attack+=(val[pr]-val[pl])*dr;
    			pr++;
    			ll+=dr;
    			rr+=dr;
    		} else if(dl<dr) {
    			attack+=(val[pr]-val[pl])*dl;
    			pl++;
    			ll+=dl;
    			rr+=dl;
    		} else {
    			attack+=(val[pr]-val[pl])*dl;
    			pr++;
    			pl++;
    			ll+=dl;
    			rr+=dl;
    		}
    		ans=max(ans,attack);
    	}
    	printf("%.7Lf
    ",ans);
    }
    int main() {
    	int T;
    	scanf("%d",&T);
    	while(T--) {
    		memset(val,0,sizeof(val));
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    [Nowcoder] 六一儿童节(拼多多)
    [Nowcoder] 大整数相乘(拼多多笔试题)
    [Nowcoder] 最大乘积(拼多多笔试题)
    [Paddle学习笔记][06][图像分类-动态图]
    [Paddle学习笔记][05][对抗生成网络]
    [Paddle学习笔记][04][图像分类]
    [Paddle学习笔记][03][数字识别]
    [Paddle学习笔记][02][MNIST转换到PNG]
    [Paddle学习笔记][01][线性回归]
    [caffe学习笔记][06][使用LeNet分类输入图片]
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10807785.html
Copyright © 2011-2022 走看看