CF704E Iron Man

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=0;bool fl=false;while(!isdigit(ch=getchar()))(ch==‘-‘)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+‘0‘);}
template<class T>il void ot(T x){if(x<0) 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=998244353;
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-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}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+5;
const double inf=1e13;
const double eps=1e-9;
int n,m;
struct node{
    int nxt,to;
}eg[2*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 1;
    if(x<-eps) return -1;
    return 0;
}
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)==0) 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)!=0) return nx<ny;
        if(Fabs(x.v-y.v)!=0)  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]=1;
    dep[x]=dep[fa[x]]+1;
    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==1) 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]-2*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=0;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=0;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)!=0) return a.p<b.p;
        return a.tp>b.tp;
    }
}e[2*N];
multiset<line>s;

int main(){
    rd(n);rd(m);
    int x,y;
    for(reg i=1;i<n;++i){
        rd(x);rd(y);
        add(x,y);
        add(y,x);
    }
    dfs(1);
    dfs2(1);

    int t,c;
    for(reg i=1;i<=m;++i){
        rd(t);rd(c);rd(x);rd(y);
        push(x,y,t,c);
    }

    ans=inf;
    for(reg i=1;i<=tot;++i){
        int num=0;
        for(reg o=0;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=1;

            e[++num].id=o;
            e[num].p=lp.bt+(lp.nd-lp.st)/lp.v;
            e[num].tp=-1;
        }
        sort(e+1,e+num+1);
        s.clear();

        for(reg j=1;j<=num;++j){
            X=e[j].p;
            if(X>ans-eps) break;
            line lp=h[i].mem[e[j].id];
            if(e[j].tp==1){
                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-1) puts("-1");
    else printf("%.10lf",ans);
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
*/

两个知识点:

1.线段集合求最小的交点。

2.树链剖分,路径放到链上转化为序列问题。

原文地址:https://www.cnblogs.com/Miracevin/p/11079279.html

时间: 2024-08-11 09:36:37

CF704E Iron Man的相关文章

ZROI 19.08.02 计算几何

1.向量基础知识 \(atan2\)可以求极角,但是不是特别精确,在坐标接近\(10^{9}\)时会出锅,安全的做法是叉积. 旋转.反射和平移等都可以抽象为矩阵,即,它们可以复合.(需要一些必修四知识) 给一个序列,每个位置表示旋转.反射.平移中的一种,求\((x,y)\)经过序列\([l,r]\)的点. 线段树维护矩乘就好了,矩阵里需要带个常数位置. Simpson积分 不会积分,告辞. 2.简单题 求点\(p\)在直线\(p_1p_2\)上的投影. 投影就是点积,直接积就行了,必修四怎么学的

计算机体系结构的铁律(iron law)

计算机体系结构的铁律可由以下公式来描述: 从Programmer的角度来看,处理器的性能就是执行程序的耗费的时间,所以用Time/Program来刻画处理器性能.而这个简单的公式背后是有非常丰富的内涵的,具体地说,就是该公式又可以展开为以下三个简单有内涵的公式. Instructions/Program:表示一个程序对应的指令数量,这部分工作主要集中在编译器领域,一般来说,指令数量越少执行速度越快.例如,用GCC编译器时,使用-O3 当然会比-O0 快不少.如果处理器支持SSE,编译器对带循环的

Meteor: Iron.Router应用实践

Iron.Router是Meteor事实标准的路由包.在学习了其提供的五花八门的功能之后,应该如何应用实践呢? 首先简要地理解一下基本组件. Route route是指一个路由规则,其组成包括:name.path.controller.<action> name是该route在程序内其他地方被引用的依据,path是该route的匹配模式,当path匹配成功时,将调用该route指定的controller.<action>,如果没有指定<action>,则调用contro

The classification and characteristics of mill mixing iron ore processing equipment

Iron equipment for manganese ore mining, which used to the largest number of iron ore and iron ore crusher crusher. Mixing mill is the use of stirring device makes the motion of grinding media and impact, shear, grinding effect, thus the crushing equ

Iron ore crushers plant

we provide crusher equipment for sale In the process of the clients buying the products, we will through a series of rigorous service style to provide clients the satisfactory and considerate service. This plant has the provision of production capaci

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

近日,由黑少微服务研发团队推出的Iron Cloud微服务开发云已经正式对外提供服务,这是国内第一家基于云端操作的微服务专业开发工具. Iron Cloud 微服务开发云(www.ironz.com)是以微服务为核心,DevOps为理念,基于Spring Cloud.Spring Boot.React.React Native.容器技术.人工智能等,面向微服务应用的开发平台:Iron Cloud 拥抱 Spring Cloud 微服务框架,帮助企业客户解决传统集中式架构转型的困难,打造大规模高可

Agriculture, Iron, and the Bantu Peoples

There is evidence of agriculture in Africa prior to 3000 B.C. It may have developed independently, but many scholars believe that the spread of agriculture and iron throughout Africa linked it to the major centers of the Near East and Mediterranean w

Iron man

儿子的手办在近期又新增一套钢铁侠,来自于淘宝的玩具推荐,这个推荐也得益于小美和他平日在淘宝商城里的各种玩具浏览,充分体现了现阶段对复仇者联盟成员的喜爱. 一套共六个,有着不同的颜色,但造型基本一致带LED的Q版钢铁侠是儿子自己在众多钢铁侠中挑选的,套装版老板还赠送了旋转陈列台,看上去很专业的样子,在当天晚上收到货后就装上电池体验了一下. 那小的圆形陈列台,上面可以放大概四到五个左右Q版钢铁侠,缓慢旋转的方式可以让陈列在上面的手办得到全方位展示,让手办更具动感. 这套玩具没有一次性给儿子,而是采用

“钢铁混搭”(Iron Mash)的作品中

 http://www.ebay.com/cln/fclzkylpful/-/173403664017/20150206html http://www.ebay.com/cln/xkw_ekdkkc/-/173707546013/20150206html http://www.ebay.com/cln/xdwfmf4/-/173528304014/20150206html http://www.ebay.com/cln/slyhk.lbbtu/-/173845391015/20150206h