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

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

链接

loj

思路

先将导轨移到原点,然后旋转坐标系,参考博客
然后分线段,每段的贡献(三角函数值)求出来,用自己喜欢的平衡树,我选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\n",ans);
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        memset(val,0,sizeof(val));
        solve();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/dsrdsr/p/10807785.html

时间: 2024-08-06 01:22:45

[SDOI2018]物理实验 set,扫描线,旋转坐标系的相关文章

bzoj5328: [Sdoi2018]物理实验

果然我还是太菜了,爆了一天才过....隔壁肉丝都不知道喊了多少句哎╮(╯▽╰)╭我又A了什么傻逼题(然鹅就是wf和国集的题QWQ) 其实这个题就是个裸题,但是我就是不会... 这个题第一步就是明显的旋转坐标系(不会的百度),注意要先平移坐标系再旋转 然后问题就变成x轴上下有一些线段,考虑覆盖长度为L的一段区间,看看区间内最接近x轴的线段的长度和(也可以直接按题意理解,好像更好懂) 线段是斜着的很难搞,但是假如覆盖了l~r的区间,那么也可以通过三角函数搞出线段长度 可以先弄一个类似离散化的东西,我

腾讯课堂的物理实验(2017计蒜客初赛第三场)

A题 在腾讯课堂的物理课上,进行了一个有趣的物理实验. 在一个长度为 LL 米的光滑轨道上,小车 A 在 00 时刻以 1\mathrm{m/s}1m/s 的速度从左端出发向右运动,小车 B 在 tt 时刻以 1\mathrm{m/s}1m/s 的速度从右端出发向左运动,两个小车的质量相等.假设所有碰撞都是弹性碰撞,也就是当两个小车相向碰撞时,他们各自会以原来的速度向相反的方向运动:小车和轨道两端发生碰撞时,小车会以原速度向反方向运动. 试求出 TT 时刻的时候,两个小车相距多远. 输入格式 输

【BZOJ3707】圈地 计算几何 旋转坐标系

链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46608743"); } 题解: 对于一个点对,如果它的连线的方程的 x 为定值 ,即为一条竖线,那么我可以把所有点以 x 为第一键值, y 为第二键值排序,然后这条线两端的第一个点与这条线段做个三角形,其面积都可能更

VPython—旋转坐标系

使用arrow( )创建三个坐标轴代表一个坐标系,其中X0-Y0-Z0为参考坐标系(固定不动),X-Y-Z为运动坐标系,这两个坐标系原点重合,运动坐标系可以绕参考坐标系或其自身旋转.在屏幕上输出一个转换矩阵,该矩阵描述了动坐标系相对于参考坐标系的姿态,矩阵第一列表示动坐标系的X轴在参考坐标系中的方向,第二列表示动坐标系的Y轴在参考坐标系中的方向,第二列表示动坐标系的Z轴在参考坐标系中的方向.显而易见,当两个坐标系姿态一致时,转换矩阵为3阶单位矩阵. 程序中按键盘的上下方向坐标系绕Y轴旋转,按左右

北航物理实验

99级物理实验试题 1. 测量电压表内阻的线路如图所示.为电阻箱,为稳压电源,其内阻可忽略不计.实验测得一组不同值时的电压表读数(见下表).试用一元线性归纳法(不要求计算相关系数和不确定度)求出.   20.0 50.0 100.0 200.0 300.0 400.0   2.80 2.72 2.60 2.38 2.20 2.04 (一元线性回归的计算公式为:) 解: 令,则(由于的有效数字多,精度高,故用做) , ,.   1 2 3 4 5 6 平均   2.8 2.72 2.6 2.33

【BZOJ3170】[Tjoi 2013]松鼠聚会 旋转坐标系

[BZOJ3170][Tjoi 2013]松鼠聚会 有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1.现在N个松鼠要走到一个松鼠家去,求走过的最短距离. Input 第一行给出数字N,表示有多少只小松鼠.0<=N<=10^5下面N行,每行给出x,y表示其家的坐标.-10^9<=x,y<=10^9 Output 表示为了聚会走的路程和最小为多少. Sample Input 6 -4 -1 -1 -2 2

「SDOI2018」物理实验

题目大意: 这题不好描述,直接看原题吧…… 题解: 很无脑的题……就是卡精度+难写.代码能力还是太差了. 其实可以直接用long double肝过去.但我的代码似乎太丑了,以至于跑得奇慢无比. 代码: #include "bits/stdc++.h" using namespace std; inline int read() { int s=0,k=1;char ch=getchar(); while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=g

Android canvas rotate():平移旋转坐标系至任意原点任意角度-------附:android反三角函数小结

自然状态下,坐标系以屏幕左上角为原点,向右是x正轴,向下是y正轴.现在要使坐标系的原点平移至任一点O(x,y),且旋转a角度,如何实现? 交待下我的问题背景,已知屏幕上有两点p1和p2,构成直线l.我要以两点的中点mid(x,y)为坐标原点,线段l的中垂线为一个轴,l为另外一个轴,做一个坐标系.切割出一个边长为d的正方形.示意图如下所示: double d = Math.sqrt((p2.x-p1.x)*(p2.x - p1.x)+(p2.y-p1.y)*(p2.y-p1.y)); //p1.p

[基础物理实验]轮换表以及仿真实验情况