bzoj5328: [Sdoi2018]物理实验
果然我还是太菜了,爆了一天才过。。。。隔壁肉丝都不知道喊了多少句哎╮(╯▽╰)╭我又A了什么傻逼题(然鹅就是wf和国集的题QWQ)
其实这个题就是个裸题,但是我就是不会。。。
这个题第一步就是明显的旋转坐标系(不会的百度),注意要先平移坐标系再旋转
然后问题就变成x轴上下有一些线段,考虑覆盖长度为L的一段区间,看看区间内最接近x轴的线段的长度和(也可以直接按题意理解,好像更好懂)
线段是斜着的很难搞,但是假如覆盖了l~r的区间,那么也可以通过三角函数搞出线段长度
可以先弄一个类似离散化的东西,我的意思是每个线段的左右端点的x坐标为断点,相邻x坐标之间可以看成一段(大概就是这样不懂评论我)
主要问题在处理出每一段最接近x轴的线段是那一条,假如搞定了这个东西,我们可以正反枚举每个段,然后能要段就要,再加上下一个段的一部分更新答案,这个双指针扫一下就好
考虑按端点的x坐标上扫描线,对于线段有一个关键的性质,就是线段不相交,这里隐含着这么一个东西:假如线段u的左端点的x坐标较小,线段v的左端点在线段u的上方/下方,直到u被删除线段的上下关系都是不变的,否则线段就相交了
换句话说,不相交满足对于在任意一条线段的左右端点x坐标框住的区间中,任意一条线段和这一条线段的上下关系不变
那么有这个东西就可以做了,用set维护一下上方最下的线段和下方最上的线段即可
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef long double LD;
const int _=1e2;
const int maxn=1e4+_;
const LD eps=1e-;
LD sqr(LD x){return x*x;}
int n; struct point{LD x,y; point(){} point(LD X,LD Y){x=X,y=Y;}};
LD getdis(point p1,point p2){return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}
LD slope(point p1,point p2){return (p2.y-p1.y)/(p2.x-p1.x);}
LD multi(point p1,point p2,point p0)
{
LD x1,y1,x2,y2;
x1=p1.x-p0.x;
y1=p1.y-p0.y;
x2=p2.x-p0.x;
y2=p2.y-p0.y;
return x1*y2-x2*y1;
} //------------------------------------------------def----------------------------------------------------- struct board
{
point A,B;
LD g;//长度变化的比值 1/cos
void getg(){g=getdis(A,B)/fabs(A.x-B.x);}
}b[maxn];bool cmp(board b1,board b2){return b1.A.y<b2.A.y;}
bool bbbbcmp(board b1,board b2){return b1.A.x<b2.A.x;} LD co,si;
point rot(point p){return point(p.x*co-p.y*si,p.y*co+p.x*si);}
void rotate()
{
LD d=getdis(b[n+].A,b[n+].B);
co=fabs(b[n+].A.x-b[n+].B.x)/d;
si=fabs(b[n+].A.y-b[n+].B.y)/d;
if(b[n+].A.x<b[n+].B.x&&b[n+].A.y<b[n+].B.y)si=-si; for(int i=;i<=n;i++)
{
b[i].A.x-=b[n+].A.x,b[i].A.y-=b[n+].A.y;
b[i].B.x-=b[n+].A.x,b[i].B.y-=b[n+].A.y; b[i].A=rot(b[i].A);
b[i].B=rot(b[i].B);
if(b[i].A.x>b[i].B.x)swap(b[i].A,b[i].B);
b[i].getg(); // printf("%.10Lf %.10Lf %.10Lf %.10Lf\n",b[i].A.x,b[i].A.y,b[i].B.x,b[i].B.y);
}
} //---------------------------------------------------rotate------------------------------------------------- LD xx[*maxn];int xlen;
bool xx_cmp(LD x1,LD x2){return x1<x2;}
int up[*maxn],dp[*maxn];//xx[i]~xx[i-1]这一段被那条线段覆盖着 struct seg
{
int id;
seg(){} seg(int ID){id=ID;}
friend bool operator <(seg s1,seg s2)
{
int x=s1.id,y=s2.id;
if(x<y)return multi(b[x].B,b[y].A,b[x].A)>;
else return multi(b[y].B,b[x].A,b[y].A)<;
}
friend bool operator >(seg s1,seg s2)
{
int x=s1.id,y=s2.id;
if(x<y)return multi(b[x].B,b[y].A,b[x].A)<;
else return multi(b[y].B,b[x].A,b[y].A)>;
}
};set< seg,less<seg> >us;set< seg,greater<seg> >ds; struct qq{int op,p;seg s; qq(){} qq(int OP,int P,seg S){op=OP,p=P,s=S;}}uq[*maxn],dq[*maxn];int uqlen,dqlen;
bool qqqqcmp(qq q1,qq q2){return q1.p==q2.p?q1.op>q2.op:q1.p<q2.p;} int lb(LD d)
{
int l=,r=xlen;
while(l<=r)
{
int mid=(l+r)/;
if(fabs(xx[mid]-d)<=eps)return mid;
if(xx[mid]>d)r=mid-;
else l=mid+;
}
}
void cover(int l1,int r1,int l2,int r2)
{
sort(b+l1,b+r1+,bbbbcmp);
sort(b+l2,b+r2+,bbbbcmp);
uqlen=dqlen=;
for(int i=l1;i<=r1;i++)
{
uq[++uqlen]=qq( ,lb(b[i].A.x)+,seg(i));
uq[++uqlen]=qq(-,lb(b[i].B.x),seg(i));
}
for(int i=l2;i<=r2;i++)
{
dq[++dqlen]=qq( ,lb(b[i].A.x)+,seg(i));
dq[++dqlen]=qq(-,lb(b[i].B.x),seg(i));
} us.clear(),ds.clear();
sort(uq+,uq+uqlen+,qqqqcmp);
sort(dq+,dq+dqlen+,qqqqcmp);
int utp=,dtp=;
for(int i=;i<=xlen;i++)
{
while(utp<=uqlen&&uq[utp].p==i&&uq[utp].op==)us.insert(uq[utp].s),utp++;
while(dtp<=dqlen&&dq[dtp].p==i&&dq[dtp].op==)ds.insert(dq[dtp].s),dtp++; if(!us.empty())up[i]=(*us.begin()).id; else up[i]=-;
if(!ds.empty())dp[i]=(*ds.begin()).id; else dp[i]=-; while(utp<=uqlen&&uq[utp].p==i&&uq[utp].op==-)us.erase(uq[utp].s),utp++;
while(dtp<=dqlen&&dq[dtp].p==i&&dq[dtp].op==-)ds.erase(dq[dtp].s),dtp++;
}
} //-----------------------------------------------cover------------------------------------------------------ int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n+;i++)
scanf("%Lf%Lf%Lf%Lf",&b[i].A.x,&b[i].A.y,&b[i].B.x,&b[i].B.y);
scanf("%Lf",&b[n+].g);
if(b[n+].A.x>b[n+].B.x)swap(b[n+].A,b[n+].B);
rotate(); //....step1....... int pp=n+; sort(b+,b+n+,cmp);
xlen=;
for(int i=;i<=n;i++)
{
if(b[i].A.y>&&pp==n+)pp=i;
xx[++xlen]=b[i].A.x;
xx[++xlen]=b[i].B.x;
}
sort(xx+,xx+xlen+);
int tp=;
for(int j=;j<=xlen;j++)
if(fabs(xx[j]-xx[tp])>eps)xx[++tp]=xx[j];
xlen=tp;
cover(pp,n,,pp-); //....step2....... LD ans=,sum=;
int j=;
for(int i=;i<=xlen;i++)
{
while(j<xlen&&(xx[j+]-xx[i-])<=b[n+].g)
{
j++;
if(up[j]!=-)sum+=(xx[j]-xx[j-])*b[up[j]].g;
if(dp[j]!=-)sum+=(xx[j]-xx[j-])*b[dp[j]].g;
}
LD num=;
if(j<xlen)
{
if(up[j+]!=-)num+=min(xx[j+]-xx[j],b[n+].g-(xx[j]-xx[i-]))*b[up[j+]].g;
if(dp[j+]!=-)num+=min(xx[j+]-xx[j],b[n+].g-(xx[j]-xx[i-]))*b[dp[j+]].g;
}
ans=max(ans,sum+num);
if(up[i]!=-)sum-=(xx[i]-xx[i-])*b[up[i]].g;
if(dp[i]!=-)sum-=(xx[i]-xx[i-])*b[dp[i]].g; // printf("%.10Lf %.10Lf %.10Lf\n",xx[i]-xx[i-1],b[up[i]].g,b[dp[i]].g);
}
j=xlen;sum=;
for(int i=xlen;i>;i--)
{
while(j>&&(xx[i]-xx[j-])<=b[n+].g)
{
if(up[j]!=-)sum+=(xx[j]-xx[j-])*b[up[j]].g;
if(dp[j]!=-)sum+=(xx[j]-xx[j-])*b[dp[j]].g;
j--;
}
LD num=;
if(j>)
{
if(up[j]!=-)num+=min(xx[j]-xx[j-],b[n+].g-(xx[i]-xx[j]))*b[up[j]].g;
if(dp[j]!=-)num+=min(xx[j]-xx[j-],b[n+].g-(xx[i]-xx[j]))*b[dp[j]].g;
}
ans=max(ans,sum+num);
if(up[i]!=-)sum-=(xx[i]-xx[i-])*b[up[i]].g;
if(dp[i]!=-)sum-=(xx[i]-xx[i-])*b[dp[i]].g;
} printf("%.10Lf\n",ans);
// break;
//....step3.......
} return ;
}
bzoj5328: [Sdoi2018]物理实验的更多相关文章
- [SDOI2018]物理实验 set,扫描线,旋转坐标系
[SDOI2018]物理实验 set,扫描线,旋转坐标系 链接 loj 思路 先将导轨移到原点,然后旋转坐标系,参考博客. 然后分线段,每段的贡献(三角函数值)求出来,用自己喜欢的平衡树,我选set. ...
- SDOI2018物理实验
/* 向量运算不会呐 抄了一个长度几百行的模板 一直过不了编译 醉了 还是抄了大佬的代码 首先把所有的线段投影到 导轨上 然后用set 分上和下分别维护一下 距离导轨最近的线段 是能够照射到的 可以证 ...
- 「SDOI2018」物理实验
题目大意: 这题不好描述,直接看原题吧…… 题解: 很无脑的题……就是卡精度+难写.代码能力还是太差了. 其实可以直接用long double肝过去.但我的代码似乎太丑了,以至于跑得奇慢无比. 代码: ...
- [JZOJ 5885] [NOIP2018模拟9.27] 物理实验 解题报告 (思维)
题目链接: https://jzoj.net/senior/#main/show/5885 题目: 题解: 把$a$数组按升序排序 我们可以枚举$x$,发现对于任意$x$,最优情况下$y$一定等于$x ...
- 【大学物理实验】01 单摆测重力加速度 的 g 计算代码
单摆测重力加速度 传统摆 (代码没保存,就截了个图) 研究单摆周期与摆长之间的关系 (依旧是g的计算) 我还不太会数据拟合
- SDOI2018
SD的题有点反人类啊... d1t1[SDOI2018]物理实验 感觉比较好想但不太好写,写了一半弃了 d1t2[SDOI2018]战略游戏 建出圆方树,每次建虚树,答案就是虚树上的原点个数减去询问的 ...
- 【转】AB实验设计思路及实验落地
这篇文章会讨论: 在什么情况下需要做 AB 实验 从产品/交互角度,如何设计一个实验 前端工程师如何打点 如何统计数据,并保证数据准确可信 如何分析实验数据,有哪些数据需要重点关注 附:如何搭建前端实 ...
- 计组CPU设计实验关键材料和关键设计
我记得这是2016春季学期搞得,参考和学习了很多别人的东西,这里小小的总结一下,逻辑性还不是太强,还需要好好整理 首先是指令集 CPU架构 外部接线架构 指令格式 机器状态自动机 这部分忘了,汗 这部 ...
- PBR(基于物理的渲染)学习笔记2
相关资料 https://www.cnblogs.com/dojo-lzz/p/13237686.html 文档:PBR学习笔记.note 链接:http://note.youdao.com/note ...
随机推荐
- oracle的split函数
PL/SQL 中没有split函数,需要自己写. 代码: create or replace type type_split as table of varchar2(50); --创建一个 typ ...
- 史上最详细的linux关于connect: network is unreachable 问题的解决方案
1.虚拟机常用连接网络方式有两种:桥接和NAT. 使用桥接模式:则保证虚拟机的网段与物理机的网段保持一致.如下: 虚拟机网卡配置: 物理机使用WiFi接入网络(我用的是WiFi,你们可能用的是有线道理 ...
- Mybatis resultMap空值映射问题
参考博客:https://www.oschina.net/question/1032714_224673 http://stackoverflow.com/questions/22852383/how ...
- JS 操作XML
loadXML = function(xmlFile) { var xmlDoc; if(window.ActiveXObject) { xmlDoc ...
- android layout
android的视图分为两类,一类是布局,另一个类是控件 一.LinearLayout(线性布局) 最常用布局之一,线性布局的特性是每添加一个控件默认会在上个控件的下面占一行. <LinearL ...
- Hadoop HDFS 常用命名
HDFS命令基本格式:hadoop fs -cmd < args > ls 命令hadoop fs -ls / 列出hdfs文件系统根目录下的目录和文件 hadoop fs -ls -R ...
- Spark学习(三): 基本架构及原理
Apache Spark是一个围绕速度.易用性和复杂分析构建的大数据处理框架,最初在2009年由加州大学伯克利分校的AMPLab开发,并于2010年成为Apache的开源项目之一,与Hadoop和St ...
- centos6.5编译安装gearmand Job Server(C)
1)下载安装包: wget https://launchpad.net/gearmand/1.2/1.1.12/+download/gearmand-1.1.12.tar.gz 2)安装编译器: yu ...
- git-flow 工作流 备忘清单
关于 git-flow 是一个 git 扩展集,按 Vincent Driessen 的分支模型提供高层次的库操作. 查看详情 ★ ★ ★ 这个备忘清单展示了 git-flow 的基本操作和效果. ★ ...
- Setup and Teardown Thread Group in Jmeter
setup和teardown有点类似于每个测试用例开始和结束时要做的动作 A Thread Group is the starting point of any Jmeter Test Plan. A ...