CF704E Iron Man
经过不懈(抄题解)努力之后,终于AC了此题。
说起来很简单。
考虑一个链上的情况,
建立直角坐标系。
横坐标是t,纵坐标是距离链开头的距离d
m个路径就是一个线段
那么能碰撞,当且仅当线段有交。
给一些线段的集合,求两两之间的第一个交点。
做法:
扫描线。
set维护线段,按照纵坐标递增,纵坐标相同按斜率递增。用全局变量X重载小于号。
加入一个线段时候,把它和它的前驱后继求交。
删除一个线段时候,把它的后继和它的前驱求交。
交点横坐标贡献给答案。
虽然不能求出前多少大的交点,甚至两条线在相交之后相对位置会改变
但是无所谓!在第一个交点出现之前,两两线段的相对顺序不变
我们只需要第一个交点。之后的操作如果横坐标大于ans,直接break!
上面求的交点一定可以得到第一个交点(自己画画图)
树上?树链剖分,直接放到直上直下的链上去做!!!!
利用树剖logn段,经典套路
实现方式:
1.注意重链头上的边归给自己。
2.线段的存储方式:
如果直接写成k*x+b的形式,b会很大,产生精度误差。而且点点相交的时候也比较麻烦。
所以采用物理方式
记录到达这个链时候的开始时间,开始位置,结束位置,速度
求交点就是相遇问题。
求横坐标为X位置的值,也是用:位移=速度*时间
eps开的是1e-9
O(nlog^2n)很不满。
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
namespace Modulo{
const int mod=;
il int ad(int x,int y){return x+y>=mod?x+y-mod:x+y;}
il int sub(int x,int y){return ad(x,mod-y);}
il int mul(int x,int y){return (ll)x*y%mod;}
il void inc(int &x,int y){x=ad(x,y);}
il void inc2(int &x,int y){x=mul(x,y);}
il int qm(int x,int y=mod-){int ret=;while(y){if(y&) ret=mul(x,ret);x=mul(x,x);y>>=;}return ret;}
template<class ...Args>il int ad(const int a,const int b,const Args &...args) {return ad(ad(a,b),args...);}
template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);}
}
namespace Miracle{
const int N=1e5+;
const double inf=1e13;
const double eps=1e-;
int n,m;
struct node{
int nxt,to;
}eg[*N];
int hd[N],cnt;
void add(int x,int y){
eg[++cnt].nxt=hd[x];
eg[cnt].to=y;
hd[x]=cnt;
}
int dfn[N],df,top[N],fa[N],id[N];
int son[N],sz[N],dep[N]; /////////////////////////
double X;//here is X!
///////////////////////// int Fabs(double x){
if(x>eps) return ;
if(x<-eps) return -;
return ;
}
struct line{
int st,nd;
double bt,v;
double friend operator &(line x,line y){
if(Fabs(x.v-y.v)){
double ny=y.st+(x.bt-y.bt)*y.v;
double tim=x.bt+(ny-x.st)/(x.v-y.v);
if(tim>y.bt-eps&&tim>x.bt-eps&&tim<y.bt+(y.nd-y.st)/y.v+eps&&tim<x.bt+(x.nd-x.st)/x.v+eps) return tim;
return inf;
}else{
if(Fabs((y.st-x.st)/x.v+x.bt-y.bt)==) return max(y.bt,x.bt);
return inf;
}
}
bool friend operator <(line x,line y){
double nx=x.st+(X-x.bt)*x.v,ny=y.st+(X-y.bt)*y.v;
if(Fabs(nx-ny)!=) return nx<ny;
if(Fabs(x.v-y.v)!=) return x.v<y.v;
if(x.st!=y.st) return x.st<y.st;
return x.nd<y.nd;
}
}; struct hl{
vector<line>mem;
int st,nd;
}h[N];
int tot; void dfs(int x){
sz[x]=;
dep[x]=dep[fa[x]]+;
for(reg i=hd[x];i;i=eg[i].nxt){
int y=eg[i].to;
if(y==fa[x]) continue;
fa[y]=x;
dfs(y);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
}
void dfs2(int x){
dfn[x]=++df;
if(!top[x]){
++tot;
if(x==) h[tot].st=x;
else h[tot].st=fa[x]; top[x]=x;
id[x]=tot;
h[tot].nd=x;
}else{
id[x]=id[top[x]];
h[id[x]].nd=x;
}
if(son[x]) top[son[x]]=top[x],dfs2(son[x]);
for(reg i=hd[x];i;i=eg[i].nxt){
int y=eg[i].to;
if(y==fa[x]) continue;
if(y==son[x]) continue;
dfs2(y);
}
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
return y;
}
void push(int x,int y,int t,int c){
double xt=t;
int anc=lca(x,y);
int dis=dep[x]+dep[y]-*dep[anc];
double yt=(double)t+(double)dis/c;
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]]){//jump x
int now=id[x];
line lp;
lp.bt=xt;
lp.st=dep[x]-dep[h[now].st];
lp.nd=;lp.v=-c;h[now].mem.pb(lp);
xt+=(double)(dep[x]-dep[h[now].st])/c;
x=fa[top[x]];
}else{//jump y
int now=id[y];
line lp;
yt-=(double)(dep[y]-dep[h[now].st])/c;
lp.bt=yt;
lp.st=;lp.nd=dep[y]-dep[h[now].st];
lp.v=c;
h[now].mem.pb(lp);
y=fa[top[y]];
}
}
if(dep[x]>dep[y]){
int now=id[x];
line lp;
lp.bt=xt;
lp.st=dep[x]-dep[h[now].st];
lp.nd=dep[y]-dep[h[now].st];lp.v=-c;h[now].mem.pb(lp);
}else{
int now=id[y];
line lp;
yt-=(double)(dep[y]-dep[x])/c;
lp.bt=yt;
lp.st=dep[x]-dep[h[now].st];lp.nd=dep[y]-dep[h[now].st];
lp.v=c;
h[now].mem.pb(lp);
}
} double ans=inf; struct ev{
double p;
int id,tp;
bool friend operator <(ev a,ev b){
if(Fabs(a.p-b.p)!=) return a.p<b.p;
return a.tp>b.tp;
}
}e[*N];
multiset<line>s; int main(){
rd(n);rd(m);
int x,y;
for(reg i=;i<n;++i){
rd(x);rd(y);
add(x,y);
add(y,x);
}
dfs();
dfs2(); int t,c;
for(reg i=;i<=m;++i){
rd(t);rd(c);rd(x);rd(y);
push(x,y,t,c);
} ans=inf;
for(reg i=;i<=tot;++i){
int num=;
for(reg o=;o<(int)h[i].mem.size();++o){
line lp=h[i].mem[o];
e[++num].id=o;
e[num].p=lp.bt;
e[num].tp=; e[++num].id=o;
e[num].p=lp.bt+(lp.nd-lp.st)/lp.v;
e[num].tp=-;
}
sort(e+,e+num+);
s.clear(); for(reg j=;j<=num;++j){
X=e[j].p;
if(X>ans-eps) break;
line lp=h[i].mem[e[j].id];
if(e[j].tp==){
s.insert(lp);
auto bc=s.lower_bound(lp);
auto tmp=bc;++tmp;
if(tmp!=s.end()){
ans=min(ans,(*tmp)&lp);
}
tmp=bc;
if(tmp!=s.begin()){
--tmp;
ans=min(ans,(*tmp)&lp);
}
}else{
auto bc=s.lower_bound(lp);
if(bc!=s.end()){
if(bc!=s.begin()){
auto pr=bc;--pr;
ans=min(ans,(*bc)&(*pr));
}
}
auto now=s.find(lp);
s.erase(now);
}
}
}
if(ans>=inf-) puts("-1");
else printf("%.10lf",ans);
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
*/
两个知识点:
1.线段集合求最小的交点。
2.树链剖分,路径放到链上转化为序列问题。
CF704E Iron Man的更多相关文章
- ZJOI2018游记Round1
广告 ZJOI2018Round2游记 All Falls Down 非常感谢学弟学妹们捧场游记虽然这是一篇假游记 ZJOI Round1今天正式落下帷幕.在这过去的三天里遇到了很多朋友,见识了很多有 ...
- zhengrui集训笔记2
Day_6 计算几何 点积\Large 点积点积 叉积\Large 叉积叉积 极角\Large 极角极角 < π\piπ :叉积判断 else :atan2 旋转\Large 旋转旋转 左乘第一 ...
- ZROI 19.08.02 计算几何
1.向量基础知识 \(atan2\)可以求极角,但是不是特别精确,在坐标接近\(10^{9}\)时会出锅,安全的做法是叉积. 旋转.反射和平移等都可以抽象为矩阵,即,它们可以复合.(需要一些必修四知识 ...
- Iron Foundry
Iron Foundry Provided by Tier 3 Iron Foundry is a project initiated by the engineers of Tier 3, an e ...
- 高级浏览器-SRWare Iron 29.0.1600.0 版本发布
SRWare Iron是德国一安全公司srware改造的Chrome(铬)命名为铁(iron)的浏览器.于2008年9月18日首次发布. 据官方介绍,Iron浏览器砍掉了Chromium原程序中的很多 ...
- 黑少微服务商店之Iron Cloud微服务开发云
近日,由黑少微服务研发团队推出的Iron Cloud微服务开发云已经正式对外提供服务,这是国内第一家基于云端操作的微服务专业开发工具. Iron Cloud 微服务开发云(www.ironz.com) ...
- 20172305 暑假作业 之 TimeCalculate & Save Iron Man
20172305 暑假作业 之 TimeCalculate & Save Iron Man TimeCalculate 项目介绍 项目名称: TimeCalculate 项目简介: 本项目基于 ...
- Gym 101170I Iron and Coal(BFS + 思维)题解
题意:有一个有向图,有些点是煤,有些点是铁,但不会同时有铁和煤.现在我要从1出发,占领可以到达的点.问最少占领几个点能同时拥有一个煤和一个铁(1不用占领). 思路:思路很秀啊.我们从1往外bfs,得到 ...
- 用户添加到sudoer列表## Allow root to run any commands anywhere root ALL=(ALL) ALL Iron ALL=(ALL) ALL
将用户添加到sudoer列表 李序锴关注 2017.12.20 15:03:25字数 605阅读 4,067 默认情况下,linux没有将当前用户列入到sudoer列表中(在redhat系列的linu ...
随机推荐
- rap安装mysql
1.yum仓库下载MySQL: yum localinstall https://repo.mysql.com//mysql80-community-release-el7-1.noarch.rpm ...
- MSSQL sql常用判断语句
.判断数据库是否存在 if exists (select * from sys.databases where name = '数据库名') drop database [数据库名] 2 判断 ...
- firefox SSL_ERROR_RX_RECORD_TOO_LONG burpsuit 报错 解决方案
禁用TLS 1.3 .在Firefox的地址栏中输入“ about:config ”. .在搜索条目“tls.version.max ”.将值从4更改为3. .值4所表示TLS 1.3,3个代表TLS ...
- 【ABAP系列】SAP ABAP 物料凭证增强
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 物料凭证增强 ...
- poj3280Cheapest Palindrome
给定一个字符串S,字符串S的长度为M(M≤2000),字符串S所含有的字符的种类的数量为N(N≤26),然后给定这N种字符Add与Delete的代价,求将S变为回文串的最小代价和. Input 第一行 ...
- Win7 VS2019安装后创建C++工程失败解决
VS2019正式上手,第1个问题创建不了工程,看起来非常类似之前VS2017更新 解决办法 https://github.com/Microsoft/msbuild/issues/4286 和上次的问 ...
- HTTP中ip地址伪造的问题以及解决办法
在真实环境下,php获取客户端ip地址的方法通常有以下几种: (1):通过$_SERVER[ "HTTP_CLIENT_IP" ] (2):通过$_SERVER[ "HT ...
- P4390 [BOI2007]Mokia 摩基亚
传送门 对于一个询问 $(xa,ya),(xb,yb)$,拆成 $4$ 个询问并容斥一下 具体就是把询问变成求小于等于 $xb,yb$ 的点数,减去小于等于 $xa-1,yb$ 和小于等于 $xb,y ...
- 如何优化MySQL千万级大表
很好的一篇博客,转载 如何优化MySQL千万级大表 原文链接::https://blog.csdn.net/yangjianrong1985/article/details/102675334 千万级 ...
- Solr的学习使用之(四)建数据库(添加Core)、表(配置schema.xml)
1.数据库数据库就相当于solr里面的核.solr4.6不能使用界面提供的的Core Admin/Add Core来建立,会报错,不懂为啥:那就采用最 简单的办法:把solr下载包里面的\solr-4 ...