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的更多相关文章

  1. ZJOI2018游记Round1

    广告 ZJOI2018Round2游记 All Falls Down 非常感谢学弟学妹们捧场游记虽然这是一篇假游记 ZJOI Round1今天正式落下帷幕.在这过去的三天里遇到了很多朋友,见识了很多有 ...

  2. zhengrui集训笔记2

    Day_6 计算几何 点积\Large 点积点积 叉积\Large 叉积叉积 极角\Large 极角极角 < π\piπ :叉积判断 else :atan2 旋转\Large 旋转旋转 左乘第一 ...

  3. ZROI 19.08.02 计算几何

    1.向量基础知识 \(atan2\)可以求极角,但是不是特别精确,在坐标接近\(10^{9}\)时会出锅,安全的做法是叉积. 旋转.反射和平移等都可以抽象为矩阵,即,它们可以复合.(需要一些必修四知识 ...

  4. Iron Foundry

    Iron Foundry Provided by Tier 3 Iron Foundry is a project initiated by the engineers of Tier 3, an e ...

  5. 高级浏览器-SRWare Iron 29.0.1600.0 版本发布

    SRWare Iron是德国一安全公司srware改造的Chrome(铬)命名为铁(iron)的浏览器.于2008年9月18日首次发布. 据官方介绍,Iron浏览器砍掉了Chromium原程序中的很多 ...

  6. 黑少微服务商店之Iron Cloud微服务开发云

    近日,由黑少微服务研发团队推出的Iron Cloud微服务开发云已经正式对外提供服务,这是国内第一家基于云端操作的微服务专业开发工具. Iron Cloud 微服务开发云(www.ironz.com) ...

  7. 20172305 暑假作业 之 TimeCalculate & Save Iron Man

    20172305 暑假作业 之 TimeCalculate & Save Iron Man TimeCalculate 项目介绍 项目名称: TimeCalculate 项目简介: 本项目基于 ...

  8. Gym 101170I Iron and Coal(BFS + 思维)题解

    题意:有一个有向图,有些点是煤,有些点是铁,但不会同时有铁和煤.现在我要从1出发,占领可以到达的点.问最少占领几个点能同时拥有一个煤和一个铁(1不用占领). 思路:思路很秀啊.我们从1往外bfs,得到 ...

  9. 用户添加到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 ...

随机推荐

  1. 聊聊redis的监控工具

    序 本文主要研究一下redis的监控工具 redis-stat redis-stat是一个比较有名的redis指标可视化的监控工具,采用ruby开发,基于redis的info命令来统计,不影响redi ...

  2. Vue访问子组件实例或子元素

    1 尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件(例如,调用子组件的方法).为了达到这个目的,你可以通过 ref 特性为这个子组件赋予一个 ID 引用 ...

  3. HashMap之扰动函数和低位掩码

    我们都知道,hashMap在实现的时候,为了寻找在数组上的位置,主要做了两件事 int hash = hash(key); int i = indexFor(key, table.length); 这 ...

  4. 如何配置JedisPool的参数

    转自:http://blog.csdn.net/huahuagongzi99999/article/details/13631579 如何配置Pool的参数 JedisPool的配置参数很大程度上依赖 ...

  5. 【Python—参数】*arg与**kwargs参数的用法

    在python中,这两个是python中的可变参数,*arg表示任意多个无名参数,类型为tuple;**kwargs表示关键字参数,为dict. # *允许你传入0个或任意个参数,这些可变参数在函数调 ...

  6. mysql 分区与性能

    数据库应用分为两类: OLTP(在线事务处理):如bolg.电子商务.网络游戏等 OLAP(在线分析处理):如数据仓库.数据集市 对于OLAP,分区可以很好的提高查询性能,应用大多数据需要频繁地扫描一 ...

  7. Tarjan(lca)

    http://codevs.cn/problem/2370 /   2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond         题目描 ...

  8. python依赖包整体迁移方法(pip)

    做个记录 python依赖包整体迁移方法

  9. JS高级 —— 普通函数、构造函数、对象方法的调用

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  10. 测试微信小程序页面的生命周期

    前言:本人是一个初学者,也是第一次写博客,敲键盘的时候还不知道发布后是什么效果,希望内容给其他初学的同学一点帮助,同时加深自己的理解.这篇随笔讲的是Page页面的生命周期,在开发中是基础中的基础,很容 ...