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 ...
随机推荐
- delphi中的idhttpserver如何才能收到idhttp发送来的exe\rar文件呢
http://zhidao.baidu.com/link?url=-q2oXqYCKBZ9OgFDEHAcQwQEY_NroHcqGvVfKW67X5sF9LdjAAB_HPXQo04VxStFVS7 ...
- curl 中关于 CURLINFO_HEADER_SIZE 的 BUG 定位及修复
curl 官方下载页面 CentOS7 默认安装的 curl 版本太低了,需要升级为最新版. 1. 问题描述 对接了一个接口,用来下载 PDF 文件.使用 curl 下载后,文件老是报错无法打开.接口 ...
- v-text、v-html、v-bind、v-show
<!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...
- poj1258Agri-Net(最小生成树)
题目链接:http://poj.org/problem?id=1258 Description Farmer John has been elected mayor of his town! One ...
- ajax基础--基本概念
1.Ajax的全称: Asynchronous Javascript And XML,就是使用is代码获取服务器数据 局部异步刷新 IP地址:用来标识查找某一台计算机 域名:ip地址太难记了,使用域名 ...
- _groovy
_groovy与beanshell类似,只是它执行的是apache groovy脚本,并返回结果. 如果定义了属性 “groovy.utilities”,属性将会被脚本引擎加载,这样就可以定义一些通用 ...
- Spring-Cloud-Alibaba-Nacos 目录
Spring-Cloud-Alibaba-Nacos 目录 学习资料 Nacos 官网(https://nacos.io/zh-cn/docs/what-is-nacos.html) Nacos 程序 ...
- java_第一年_JavaWeb(9)
JavaBean是一个遵循某种特定写法的Java类,有以下特点: 必需具有一个无参的构造函数 属性必需私有化 私有化的属性必需通过public类型的方法暴露给其它程序,其方法命名也有一定的规范 范例: ...
- P3914染色计数
题目描述 有一颗\(N\)个节点的树,节点用\(1,2,\cdots,N\)编号.你要给它染色,使得相邻节点的颜色不同.有\(M\)种颜色,用\(1,2,\cdots,M\)编号.每个节点可以染\(M ...
- POJ 3764 The xor-longest Path (01字典树)
<题目链接> 题目大意: 给定一颗$n$个节点$(n\leq10^5)$,有边权的树,其边权$(0\leq w < 2^{31})$.让你求出这棵树上任意两个节点之间的异或最大值. ...