4515: [Sdoi2016]游戏

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit:
304  Solved: 129
[Submit][Status][Discuss]

Description

Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,
若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t
的路径。
他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。

Input

第一行两个数字 n、m,表示树的点数和进行的操作数。
接下来 n−1 行,每行三个数字 u、v、w,表示树上有一条连接 u、v 的边,长度是 w。
接下来 m 行。每行第一个数字是 1 或 2。
若第一个数是 1,表示 Alice 进行操作,接下来四个数字 s、t、a、b。
若第一个数是 2,表示 Bob 进行操作,接下来四个数字 s、t。

Output

每当 Bob 进行操作,输出一行一个数,表示他能够选择的最小的数字

Sample Input

3 5
1 2 10
2 3 20
2 1 3
1
2 3 5 6
2 2 3
1 2 3 -5 -6
2 2 3

Sample Output

123456789123456789
6
-106

HINT

n≤100000,m≤100000,∣a∣≤10000,0<=w,|b|<=10^9

Source

鸣谢Menci上传

Solution

仍旧是李超线段树维护半平面交,唯一不同的是这里有了一个距离的定义

只需要在比较的时候带入端点和终点的距离即可,至于李超线段树,此处安利一个非常好的文章:戳这里

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long read()
{
long long x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-')f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 100100
struct EdgeNode{int next,to;long long len;}edge[maxn<<];
int head[maxn],cnt;
void add(int u,int v,long long w)
{
cnt++;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].len=w;
}
void insert(int u,int v,long long w) {add(u,v,w); add(v,u,w);}
int n,m;
//--------------------------------------------------------------------------------------------------------
int pl[maxn],sz,pr[maxn],size[maxn],deep[maxn],son[maxn],top[maxn],fa[maxn];long long dis[maxn],pre[maxn];
void dfs_1(int x)
{
size[x]=;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].to!=fa[x])
{
fa[edge[i].to]=x;
deep[edge[i].to]=deep[x]+;
dis[edge[i].to]=dis[x]+edge[i].len;
dfs_1(edge[i].to);
if (size[son[x]]<size[edge[i].to]) son[x]=edge[i].to;
size[x]+=size[edge[i].to];
}
}
void dfs_2(int x,int chain)
{
pl[x]=++sz; pre[sz]=dis[x]; top[x]=chain;
if (son[x]) dfs_2(son[x],chain);
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].to!=fa[x] && edge[i].to!=son[x])
dfs_2(edge[i].to,edge[i].to);
pr[x]=sz;
}
int LCA(int x,int y)
{
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if (deep[x]>deep[y]) swap(x,y);
return x;
}
//--------------------------------------------------------------------------------------------------------
long long f(long long x,long long k,long long b) {return k*x+b;}
struct TreeNode{long long a,b,minn;}tree[maxn<<];
#define inf 123456789123456789LL
void Build(int now,int l,int r)
{
tree[now].a=; tree[now].b=tree[now].minn=inf;
if (l==r) return;
int mid=(l+r)>>;
Build(now<<,l,mid); Build(now<<|,mid+,r);
}
long long Query(int now,int l,int r,int L,int R)
{
long long re=min(f(pre[L],tree[now].a,tree[now].b),f(pre[R],tree[now].a,tree[now].b));
if (l==L && r==R) return min(re,tree[now].minn);
int mid=(l+r)>>;
if (R<=mid) return min(re,Query(now<<,l,mid,L,R));
else if (L>mid) return min(re,Query(now<<|,mid+,r,L,R));
else return min(re,min(Query(now<<,l,mid,L,mid),Query(now<<|,mid+,r,mid+,R)));
}
void Change(int now,int l,int r,long long a,long long b)
{
int mid=(l+r)>>,fl,fr,fm;
fl=(f(pre[l],tree[now].a,tree[now].b)>f(pre[l],a,b));
fr=(f(pre[r],tree[now].a,tree[now].b)>f(pre[r],a,b));
fm=(f(pre[mid],tree[now].a,tree[now].b)>f(pre[mid],a,b));
if (fl&fr&fm)
{
tree[now].a=a;tree[now].b=b;tree[now].minn=min(tree[now].minn,min(f(pre[l],a,b),f(pre[r],a,b)));
return;
}
if (!(fl|fr|fm)) return;
if (fm)
{
if (fr) Change(now<<,l,mid,tree[now].a,tree[now].b);
else Change(now<<|,mid+,r,tree[now].a,tree[now].b);
tree[now].a=a;tree[now].b=b;tree[now].minn=min(tree[now].minn,min(f(pre[l],a,b),f(pre[r],a,b)));
}
if (!fm)
if (!fr) Change(now<<,l,mid,a,b);
else Change(now<<|,mid+,r,a,b);
tree[now].minn=min(tree[now].minn,min(tree[now<<].minn,tree[now<<|].minn));
}
void change(int now,int l,int r,int L,int R,long long a,long long b)
{
if (L<=l && R>=r) {Change(now,l,r,a,b); return;}
int mid=(l+r)>>;
if (L<=mid) change(now<<,l,mid,L,R,a,b);
if (R>mid) change(now<<|,mid+,r,L,R,a,b);
tree[now].minn=min(tree[now].minn,min(tree[now<<].minn,tree[now<<|].minn));
}
//--------------------------------------------------------------------------------------------------------
void Solve_Insert(int s,int t,long long a,long long b)
{
int lca=LCA(s,t); int x=s,y=t;
while (top[x]!=top[lca])
{
change(,,n,pl[top[x]],pl[x],-a,a*dis[s]+b);
x=fa[top[x]];
}
change(,,n,pl[lca],pl[x],-a,a*dis[s]+b);
while (top[y]!=top[lca])
{
change(,,n,pl[top[y]],pl[y],a,dis[s]*a-dis[lca]**a+b);
y=fa[top[y]];
}
if (y!=lca) change(,,n,pl[lca]+,pl[y],a,dis[s]*a-dis[lca]**a+b);
}
long long Solve_Query(int s,int t)
{
int x=s,y=t; long long re=inf;
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
re=min(Query(,,n,pl[top[x]],pl[x]),re);
x=fa[top[x]];
}
if (deep[x]>deep[y]) swap(x,y);
re=min(Query(,,n,pl[x],pl[y]),re);
return re;
}
//--------------------------------------------------------------------------------------------------------
int main()
{
// freopen("menci_game.in","r",stdin);
// freopen("menci_game.out","w",stdout);
n=read();m=read(); long long w;
for (int u,v,i=; i<=n-; i++)
u=read(),v=read(),w=(long long)read(),insert(u,v,w);
dfs_1(); dfs_2(,); Build(,,n);
while (m--)
{
int opt=read();
if (opt==)
{
int s=read(),t=read();long long a=read(),b=read();
Solve_Insert(s,t,a,b);
}
if (opt==)
{
int s=read(),t=read();
printf("%lld\n",Solve_Query(s,t));
}
}
return ;
}

考场上,看到这个题,这不是裸树链剖分么,线段树维护半平面交,裸李超线段树啊,Clrs的模版上有哎,虽然我没写过,但是我知道大体的方法啊,然后开始码,码到最后连暴力都没打,然后愉快滚粗TAT/...

【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交的更多相关文章

  1. 【xsy3423】党² 线段树+李超线段树or动态半平面交

    本来并不打算出原创题的,此题集CF542A和sk的灵感而成,算个半原创吧. 题目大意: 给定有$n$个元素的集合$P$,其中第$i$个元素中包含$L_i,R_i,V_i$三个值. 给定另一个有$n$个 ...

  2. bzoj 4445 小凸想跑步 - 半平面交

    题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...

  3. BZOJ 4445 [Scoi2015]小凸想跑步:半平面交

    传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...

  4. BZOJ.3938.Robot(李超线段树)

    BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最 ...

  5. 洛谷P4069 [SDOI2016]游戏(李超线段树)

    题意 题目链接 Sol 这题细节好多啊qwq..稍不留神写出一个小bug就要调1h+.. 思路就不多说了,把询问区间拆成两段就是李超线段树板子题了. 关于dis的问题可以直接维护. // luogu- ...

  6. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  7. bzoj 4515: 游戏 树链剖分+线段树

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4515 题解: 先让我%一发lych大佬点我去看dalao的题解 讲的很详细. 这里纠正一 ...

  8. bzoj 2732 射箭 半平面交

    2732: [HNOI2012]射箭 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2531  Solved: 848[Submit][Status] ...

  9. BZOJ 1038 ZJOI2008 瞭望塔 半平面交

    题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 这次用半平面交写了一遍--求出半平面交之后.枚举原图和半平面交的 ...

随机推荐

  1. Hibernate总结2 API和配置文件

    1,Configuration 配置 获取config配置文件的方法 Configuration cfg = new Configuration(); cfg.下面的方法 configure() co ...

  2. Entity Framework 迁移命令 详解

    一.Entity Framework 迁移命令(get-help EntityFramework) Enable-Migrations 启用迁移 Add-Migration 为挂起的Model变化添加 ...

  3. 03Spring_bean的创建和作用域以及生命周期

    bean的三种创建方式: 方式一: 使用类构造器实例化对象 <!-- 方式一  使用构造器(无参数)实例化对象  --> <bean id="bean1" cla ...

  4. Web API删除JSON格式的文件记录

    Insus.NET的系列Web Api学习文章,这篇算是计划中最后一篇了,删除JSON格式的文件记录.前一篇<Web Api其中的PUT功能演示>http://www.cnblogs.co ...

  5. Windows 8.1 新增控件之 AppBar

    Windows 8.1 与Windows 8 相比已经有了很多改进,从ITPro 角度这篇文章<What's New in Windows 8.1>已经表述的很详细.对开发者来说,最明显的 ...

  6. Tree Traversals

    Tree Traversals 原题链接 常见的二叉树遍历的题目,根据后序遍历和中序遍历求层次遍历. 通过后序遍历和中序遍历建立起一棵二叉树,然后层序遍历一下,主要难点在于树的建立,通过中序遍历和后序 ...

  7. getSelection、range 对象属性,方法理解,解释

    网上转了一圈发现没有selection方面的解释,自己捣鼓下 以这段文字为例子.. <p><b>法国国营铁路公司(SNCF)20日承认,</b>新订购的2000列火 ...

  8. redis 学习笔记(4)-HA高可用方案Sentinel配置

    上一节中介绍了master-slave模式,在最小配置:master.slave各一个节点的情况下,不管是master还是slave down掉一个,“完整的”读/写功能都将受影响,这在生产环境中显然 ...

  9. 如何在 ie6 中使用 "localStorage"

    好吧,我只是个标题党,ie6 下根本无法使用跟 h5 沾边的 localStorage.今天要向大家介绍的是 ie 特有的 userData 的存储方式,并且对它进行封装,使得不支持 localSto ...

  10. 基于DDD的.NET开发框架 - ABP领域服务

    返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...