趁着我把李超树忘个一干二净的时候来复习一下吧,毕竟马上NOI了。

题解:看着那个dis就很不爽,直接把它转换成深度问题,然后一条直线x->y,假设其lca为z,可以拆分成x->z和z->y两条路径,然后将函数分成两段即可,把式子转换为以节点深度为变量的一次函数,求解最值,树链剖分+李超树求解,保留函数最小值即可。其实也挺裸的,但码量有点大(毕竟我写code一贯行数少+紧凑,写122行算大了),不过都很套路。

然后下面讲一下李超树:

首先覆盖还是原样覆盖,对于修改的区间[l,r],假设函数是kx+b,可以如下求解:初始化函数y=123456789123456789,然后开始覆盖区间。如果左右端点都比原函数小,说明可以直接覆盖。如果左右端点都比原函数大,说明此函数无用,直接退出即可。反之,保留在函数中以最小值出现较长的函数,然后把较短的在其左/右半部分递归处理。

至于查询操作,如果该区间已经被线段覆盖,则直接取询问左右端点的最小值即可,写法上,与普通的线段树有一些不同(根据我的代码习惯)。

注意保留区间最小值,方便查询。

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N=1e5+;
const ll inf=123456789123456789ll;
int n,m,cnt,hd[N],v[N<<],nxt[N<<],w[N<<],sz[N],son[N],fa[N],pos[N],id[N],top[N],lk[N<<];
ll ans,d[N],val[N<<],lb[N<<];
bool lazy[N<<];
void adde(int x,int y,int z){v[++cnt]=y,nxt[cnt]=hd[x],w[cnt]=z,hd[x]=cnt;}
void dfs(int u)
{
sz[u]=;
for(int i=hd[u];i;i=nxt[i])
if(v[i]!=fa[u])
{
fa[v[i]]=u,d[v[i]]=d[u]+w[i],dfs(v[i]),sz[u]+=sz[v[i]];
if(sz[v[i]]>sz[son[u]])son[u]=v[i];
}
}
void dfs2(int u,int tp)
{
id[pos[u]=++cnt]=u,top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i=hd[u];i;i=nxt[i])if(v[i]!=fa[u]&&v[i]!=son[u])dfs2(v[i],v[i]);
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])swap(x,y);
x=fa[top[x]];
}
return d[x]<d[y]?x:y;
}
void build(int l,int r,int rt)
{
val[rt]=inf;
if(l==r)return;
int mid=l+r>>;
build(lson),build(rson);
}
void pushdown(int l,int r,int rt)
{
if(l<r)val[rt]=min(val[rt<<],val[rt<<|]);else val[rt]=inf;
if(lazy[rt])val[rt]=min(val[rt],min(d[id[l]]*lk[rt],d[id[r]]*lk[rt])+lb[rt]);
}
void modify(int l,int r,int rt,int u,ll v)
{
if(!lazy[rt])lazy[rt]=,lk[rt]=u,lb[rt]=v;
else{
ll x1=d[id[l]]*u+v,y1=d[id[r]]*u+v;
ll x2=d[id[l]]*lk[rt]+lb[rt],y2=d[id[r]]*lk[rt]+lb[rt];
int mid=l+r>>;
if(x1<=x2&&y1<=y2)lk[rt]=u,lb[rt]=v;
else if(x1>=x2&&y1>=y2)return;
else if(u<lk[rt])
{
ll tmp=(v-lb[rt])/(lk[rt]-u)+;
if(tmp<=d[id[mid]])swap(u,lk[rt]),swap(v,lb[rt]),modify(lson,u,v);
else modify(rson,u,v);
}
else{
ll tmp=(lb[rt]-v-)/(u-lk[rt]);
if(tmp>d[id[mid]])swap(u,lk[rt]),swap(v,lb[rt]),modify(rson,u,v);
else modify(lson,u,v);
}
}
pushdown(l,r,rt);
}
void insert(int L,int R,int u,ll v,int l,int r,int rt)
{
if(L<=l&&r<=R){modify(l,r,rt,u,v);return;}
int mid=l+r>>;
if(L<=mid)insert(L,R,u,v,lson);
if(R>mid)insert(L,R,u,v,rson);
pushdown(l,r,rt);
}
void query(int L,int R,int l,int r,int rt)
{
if(L==l&&r==R){ans=min(ans,val[rt]);return;}
if(lazy[rt])ans=min(ans,min(d[id[L]]*lk[rt],d[id[R]]*lk[rt])+lb[rt]);
int mid=l+r>>;
if(R<=mid)query(L,R,lson);
else if(L>mid)query(L,R,rson);
else query(L,mid,lson),query(mid+,R,rson);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y,z;i<n;i++)scanf("%d%d%d",&x,&y,&z),adde(x,y,z),adde(y,x,z);
dfs(),cnt=,dfs2(,);
build(,n,);
while(m--)
{
int op,x,y,z,u,v;scanf("%d%d%d",&op,&x,&y);
if(op==)
{
scanf("%d%d",&u,&v);
z=lca(x,y);
ll tmp=d[x]*u+v;
while(top[x]!=top[z])insert(pos[top[x]],pos[x],-u,tmp,,n,),x=fa[top[x]];
insert(pos[z],pos[x],-u,tmp,,n,);
tmp-=(d[z]<<)*u;
while(top[y]!=top[z])insert(pos[top[y]],pos[y],u,tmp,,n,),y=fa[top[y]];
insert(pos[z],pos[y],u,tmp,,n,);
}
else{
ans=inf;
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])swap(x,y);
query(pos[top[x]],pos[x],,n,);
x=fa[top[x]];
}
if(d[x]>d[y])swap(x,y);
query(pos[x],pos[y],,n,);
printf("%lld\n",ans);
}
}
}

[SDOI2016]游戏(树剖+李超树)的更多相关文章

  1. [SDOI2016]游戏 树剖+李超树

    目录 链接 思路 update 代码 链接 https://www.luogu.org/problemnew/show/P4069 思路 树剖+超哥线段树 我已经自毙了,自闭了!!!! update ...

  2. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  3. BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

    BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树 题意: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastan ...

  4. BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...

  5. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

  6. 【BZOJ5210】最大连通子块和 树剖线段树+动态DP

    [BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...

  7. [LNOI2014]LCA(树剖+线段树)

    \(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...

  8. [CF1007D]Ants[2-SAT+树剖+线段树优化建图]

    题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...

  9. 2018.08.30 NOIP模拟 graph(dfs序/树剖+线段树)

    [描述] 给你一个图,一共有 N 个点,2*N-2 条有向边. 边目录按两部分给出 1. 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点 到达. 2. 接下来的 N ...

随机推荐

  1. C++面试常见问题——11重载、覆盖、隐藏

    重载.覆盖.隐藏 重载 在同一类定义的成员函数中,参数不同的同名函数为重载关系.重载与虚函数无关. class A{ private: int x; public: void fun(int); // ...

  2. 微信小程序—页面跳转

    问题: 实现页面跳转:index页面通过按钮跳转到next页面 方法: 1.页面index.wxml增加一个按钮 // index.wxml <button bindtap="jump ...

  3. 从三星官方uboot开始移植

    移植前的准备 下载 android_uboot_smdkv210.tar.bz2 这个文件 开始移植 本人使用的开发板是九鼎的 x210,在三星 uboot 的主 Makefile 中找到了类似的 s ...

  4. 记一次 springboot 参数解析 bug调试 HandlerMethodArgumentResolver

    情况描述 前端输入框输入中文的横线 -- ,到后台接收时变成了 &madsh;$mdash 正常应该显示成这样: bug调试思路记录 最开始完全没有向调试源码方面想,试了不少方法,都没解决,没 ...

  5. 如何将dmp文件导入到Oracle

    一.概述 在将dmp文件导入到Oracle中之前,需要先创建一个orcale用户.然后使用该用户名和密码,以imp的方式将数据导入到oracle中. 二.执行步骤 1.登陆oracle数据库 a.sq ...

  6. C#:string、stringBuffer、stringBuilder的区别

    好脑子不如烂笔头,总是记不住,记下来吧 依然 搬运 地址: http://blog.csdn.net/qq_28187979/article/details/76607253 ------------ ...

  7. Golang的选择结构-if语句

    Golang的选择结构-if语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.选择语句应用场景概述 选择结构也称为条件判断,生活中关于判断的场景也非常的多,比如: ()登录Q ...

  8. GNS3 模拟icmp分片不可达

    R1 : conf t int f0/0 no shutdown ip add 192.168.1.1 255.255.255.0 no ip routing end R2 f0/0: conf t ...

  9. (转)ERROR 2002 (HY000): Can't connect to local MySQL server through socket '***' (2)

    有时候,当我们使用“mysql”.“mysqladmin”.“mysqldump”等命令管理数据库时,服务器抛出类似如下错误: 1 ERROR 2002 (HY000): Can't connect ...

  10. Web安全测试学习笔记 - vulhub环境搭建

    Vulhub和DVWA一样,也是开源漏洞靶场,地址:https://github.com/vulhub/vulhub 环境搭建过程如下: 1. 下载和安装Ubuntu 16.04镜像,镜像地址:htt ...