首页 > 其他分享 >P4069 [SDOI2016] 游戏

P4069 [SDOI2016] 游戏

时间:2025-01-10 18:37:15浏览次数:1  
标签:游戏 int ll son dfn SDOI2016 lca P4069 dis

P4069 [SDOI2016] 游戏

题目描述

Alice 和 Bob 在玩一个游戏。

游戏在一棵有 \(n\) 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 \(123456789123456789\)。

有时,Alice 会选择一条从 \(s\) 到 \(t\) 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 \(r\),若 \(r\) 与 \(s\) 的距离是 \(dis\),那么 Alice 在点 \(r\) 上添加的数字是 \(a\times dis+b\)。

有时,Bob 会选择一条从 \(s\) 到 \(t\) 的路径。他需要先从这条路径上选择一个点,再从那个点上选择一个数字。

Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。

数据范围

对于所有数据,\(n\le 10^5,0\le w, |b|\le 10^9\)。

Solution:

这下不得不在机房打 game 了

看到树上路径问题我们不难想到树链剖分.

看到贡献 \(y=k*dis+b\) 很难不想到李超线段树,我们把一条路径拆成上行链和下行链:(s,lca),(lca,t)

我们以 \(dfn\) 为x轴,贡献为y轴建立李超线段树,那么在该坐标系下的一条直线的表达式其实是 :
\(y=k*dis[rid_{x}]+b\)
由于 \(dis\) 关于 \(dfn\) 的函数在每一条重链上是单调的,所以我们也就能保证插入的这条线段是单调的。

然后我们仔细的思考一下贡献:

对于上行链:
\(y=(-k)x+(dis_s*k+b)\)
对于下行链:
\(y=(k)x+(dis_s+2dis_{lca}+b)\)

然后要注意一下的是,由于这题我们需要区间查询,所以我们在 query 时需要注意查询的边界问题,详见代码。

然后这题就换乐的做完了。

Code:

#include<bits/stdc++.h>
#define ll long long
#define int long long
const ll inf=123456789123456789;
const int N=1e5+5;
using namespace std;
int n,m,tot;
ll dis[N],dep[N],dfn[N],fa[N],top[N],son[N],siz[N],rid[N];
struct line{
    ll k,b;
}q[N*20];
inline ll hight(ll x,int id)
{
    return q[id].k*(dis[rid[x]])+q[id].b;
}
inline ll Min(ll x,ll y){return x<y ? x : y;}
struct Segment_Tree{
    struct Tree{
        int id;
        ll ans;
    }t[N<<2];
    #define ls x<<1
    #define rs x<<1|1
    void build(int x,int l,int r)
    {
        t[x].ans=inf;
        if(l==r)return ;
        int mid=l+r>>1;
        build(ls,l,mid);build(rs,mid+1,r);
    }
    void pushup(int x){t[x].ans=Min(t[x].ans,Min(t[ls].ans,t[rs].ans));}
    void upd(int x,int l,int r,int L,int R,int k)
    {
        int mid=l+r>>1;
        if(L<=l&&r<=R)
        {
            ll h0=hight(l,t[x].id),h1=hight(mid,t[x].id),h2=hight(r,t[x].id);
            ll H0=hight(l,k),H1=hight(mid,k),H2=hight(r,k);
            t[x].ans=Min(t[x].ans,Min(H0,H2));
            if(H0<h0&&H2<h2){t[x].id=k;return ;}
            if(H0>=h0&&H2>=h2){return ;}
            if(q[k].k<q[t[x].id].k)
            {
                if(H1<h1){upd(ls,l,mid,L,R,t[x].id);t[x].id=k;}
                else upd(rs,mid+1,r,L,R,k);
            }
            else
            {
                if(H1<h1){upd(rs,mid+1,r,L,R,t[x].id);t[x].id=k;}
                else upd(ls,l,mid,L,R,k);
            }
        }
        if(L<=mid)upd(ls,l,mid,L,R,k);
        if(mid<R) upd(rs,mid+1,r,L,R,k);
        pushup(x);
        return ;
    }
    void query(int x,int l,int r,int L,int R,ll &res)
    {
        if(L<=l&&r<=R){res=Min(res,t[x].ans);return ;}
        ll tmp=Min(hight(max(l,L),t[x].id),hight(min(r,R),t[x].id));
        if(t[x].id)res=Min(res,tmp);
        int mid=l+r>>1;
        if(L<=mid)query(ls,l,mid,L,R,res);
        if(mid<R) query(rs,mid+1,r,L,R,res);
    }
    #undef ls
    #undef rs
}T;
struct Node{
    int y;
    ll w;
};
vector<Node> E[N];
void dfs1(int x,int ff)
{
    dep[x]=dep[ff]+1;fa[x]=ff;siz[x]=1;
    for(Node u : E[x])
    {
        if(u.y==fa[x])continue;
        dis[u.y]=dis[x]+u.w;
        dfs1(u.y,x);
        siz[x]+=siz[u.y];
        son[x] = siz[son[x]] > siz[u.y] ? son[x] : u.y;
    }
}
void dfs2(int x,int tp)
{
    dfn[x]=++dfn[0];top[x]=tp;rid[dfn[0]]=x;
    if(!son[x])return ;
    dfs2(son[x],tp);
    for(Node u : E[x])
    {
        if(u.y==fa[x]||u.y==son[x])continue;
        dfs2(u.y,u.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]];
    }
    return dep[x]<dep[y] ? x : y;
}
void chain_upd(int x,int y)
{
    while(top[x]!=top[y])
    {
        T.upd(1,1,n,dfn[top[x]],dfn[x],tot);
        x=fa[top[x]];
    }
    T.upd(1,1,n,dfn[y],dfn[x],tot);
}
ll chain_query(int s,int t)
{
    int lca=LCA(s,t),x=s,y=t;
    ll res=inf;
    while(top[x]!=top[lca])
    {
        T.query(1,1,n,dfn[top[x]],dfn[x],res);
        x=fa[top[x]];
    }
    while(top[y]!=top[lca])
    {
        T.query(1,1,n,dfn[top[y]],dfn[y],res);
        y=fa[top[y]];
    }
    if(dfn[x]<dfn[y])
    {
        T.query(1,1,n,dfn[x],dfn[y],res);
    }
    else
    {
        T.query(1,1,n,dfn[y],dfn[x],res);
    }
    return res;
}
void work()
{
    cin>>n>>m;
    for(int i=1,x,y;i<n;i++)
    {
        ll w;
        cin>>x>>y>>w;
        E[x].push_back({y,w});
        E[y].push_back({x,w});
    }
    dfs1(1,0);dfs2(1,1);
    T.build(1,1,n);
    q[tot]={0,inf};
    for(int i=1,opt,s,t;i<=m;i++)
    {
        ll k,b;
        cin>>opt>>s>>t;
        int lca=LCA(s,t);
        if(opt&1)
        {
            cin>>k>>b;
            q[++tot]={-k,k*dis[s]+b};chain_upd(s,lca);
            q[++tot]={k,k*(dis[s]-dis[lca]*2)+b};chain_upd(t,lca);
        }
        else
        {
            ll ans=chain_query(s,t);
            printf("%lld\n",ans);
        }
    }
}
#undef ll
#undef int
int main()
{
    //freopen("P4069.in","r",stdin);
    //freopen("P4069.out","w",stdout);
    work();
    return 0;
}

标签:游戏,int,ll,son,dfn,SDOI2016,lca,P4069,dis
From: https://www.cnblogs.com/LG017/p/18664478

相关文章

  • M5Stack 发布全双工通信语音识别硬件;雷蛇发布 AI 游戏伴侣 Project AVA,实时指导复盘
      开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑......
  • 最强卡皇5090登场,游戏玩家吵翻天?
    近日在CES大会上,老黄宣布RTX5090正式发布,价格竟高达16499元!自从显卡被大家熟知后,大家一直对一个话题在网上争论不休,那就是游戏显卡和专业图形显卡之间到底哪个更胜一筹?很多游戏玩家认为,所谓的“专业图像显卡”就是给游戏显卡改了个名,以更高价格去割韭菜;但又有一些用户出来为其正......
  • 计算机毕业设计Python深度学习游戏推荐系统 Django PySpark游戏可视化 游戏数据分析
    温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO......
  • 大闹天宫更始版H5网页游戏一键端+GM模式+安装教程
    今天为大家带来一款怀旧网单《大闹天宫更始版H5网页游戏》的游戏架设,仅供怀旧,本人已经安装游戏成功,特此带来详细安装教程。视频演示https://githubs.xyz/show/331.mp4 亲测截图   架设步骤关闭默认杀毒软件和其它自己下的杀毒软件 ,一定要检查关闭!!!!  打开windows......
  • 【游戏设计原理】57 - 协同效应
    协同效应(Synery)原文介绍了协同效应,并举了游戏中的三个例子,游戏玩家创造性的组合,游戏机制的组合,锻造系统。当然游戏中的协同效应还有许多体现方式,以下是一些具体例子:1.角色技能组合在多人角色扮演游戏(RPG)中,不同角色的技能组合可能会产生更强的效果。例如,在《魔兽世界......
  • 从 0 到 1:实现一个基于零知识证明的寻宝游戏
    作者:hello2jie本教程指导你使用Minao1js 开发一个去中心化应用(DApp),构建一个基于零知识证明(ZKP)的寻宝游戏。游戏中,玩家扮演精英盗贼,需完成一系列盗宝任务。通过零知识证明,玩家可以向系统展示任务完成的真实性,同时保护任务细节(如密码、路线或地点等)。整个游戏采用去中心......
  • RaceGame-Qt游戏项目构建-游戏地图
    RaceGame-Qt游戏项目构建-游戏地图游戏地图概述游戏界面固定为450px*800px;游戏地图由10px*10px像素的方块构成,采用等比缩放记录在一个45*80的array容器中。GameMap相关类GameMap相关类放在gamemap.h头文件中,对应的源文件是gamemap.cpp。一、classGameMa......
  • RaceGame-Qt游戏项目构建-图形界面
    RaceGame-Qt游戏项目构建-图形界面Qt提供了很多图形库,可以直接使用,绘制游戏地图、更新玩家位置,显示操作按钮等。游戏的主体逻辑已经通过Player类和GameMap类实现,只需要根据玩家信息、地图信息,绘制出图形化界面即可。游戏界面概述游戏界面的绘制主要包括:地图/墙体,玩家,操作......
  • P1080 [NOIP2012 提高组] 国王游戏
    P1080[NOIP2012提高组]国王游戏题目恰逢H国国庆,国王邀请\(n\)位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这\(n\)位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的......
  • RaceGame-Qt游戏项目构建-游戏框架
    RaceGame-Qt游戏项目构建-游戏框架游戏企划使用Qt图形化界面开发一款名为RaceGame的小游戏,游戏玩法是4方玩家(方块)在带有墙体的地图中以一定速度、一定方向前进,碰到墙体会反弹,最终玩家按照到达目的地的先后顺序排名。游戏过程中,玩家可以通过界面上的Button按钮进行释放技能,......