原题传送门

看到这种题,想都不用想,先写一个树链剖分

然后发现修改操作增加的是等差数列,这使我们想到了李超线段树

先进性树剖,然后用李超线段树维护区间最小,这样就做完了(写码很容易出错)

复杂度为\(O(n\log^3n)\),少见的复杂度啊qaq,但常数不用怕

#include <bits/stdc++.h>
#define ll long long
#define N 100005
#define M 100005
#define inf 123456789123456789LL
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline ll read()
{
register ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register ll x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[25];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline ll Min(register ll a,register ll b)
{
return a<b?a:b;
}
struct edge{
int to,next;
ll v;
}e[M<<1];
int head[N],cnt=0;
inline void add(register int u,register int v,register ll w)
{
e[++cnt]=(edge){v,head[u],w};
head[u]=cnt;
}
inline ll f(register ll x,register ll k,register ll b)
{
return x*k+b;
}
struct node{
ll a,b,minn;
}tr[N<<2];
int n,m;
int size[N],fa[N],son[N],dep[N];
int pl[N],top[N],tot=0;
ll dis[N],pre[N];
inline void build(register int x,register int l,register int r)
{
tr[x].a=0,tr[x].b=tr[x].minn=inf;
if(l==r)
return;
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
inline void dfs1(register int x)
{
size[x]=1;
for(register int i=head[x];i;i=e[i].next)
if(e[i].to!=fa[x])
{
fa[e[i].to]=x;
dep[e[i].to]=dep[x]+1;
dis[e[i].to]=dis[x]+e[i].v;
dfs1(e[i].to);
if(size[e[i].to]>size[son[x]])
son[x]=e[i].to;
size[x]+=size[e[i].to];
}
}
inline void dfs2(register int x,register int t)
{
pl[x]=++tot,pre[tot]=dis[x],top[x]=t;
if(son[x])
dfs2(son[x],t);
for(register int i=head[x];i;i=e[i].next)
if(e[i].to!=son[x]&&e[i].to!=fa[x])
dfs2(e[i].to,e[i].to);
}
inline int getlca(register int x,register int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
x^=y^=x^=y;
x=fa[top[x]];
}
if(dep[x]>dep[y])
x^=y^=x^=y;
return x;
}
inline void Change(register int x,register int l,register int r,register ll a,register ll b)
{
int mid=l+r>>1,fl,fr,fm;
fl=(f(pre[l],tr[x].a,tr[x].b)>f(pre[l],a,b));
fr=(f(pre[r],tr[x].a,tr[x].b)>f(pre[r],a,b));
fm=(f(pre[mid],tr[x].a,tr[x].b)>f(pre[mid],a,b));
if(fl&&fr&&fm)
{
tr[x].a=a,tr[x].b=b,tr[x].minn=Min(tr[x].minn,Min(f(pre[l],a,b),f(pre[r],a,b)));
return;
}
if(!(fl|fr|fm))
return;
if(fm)
{
if(fr)
Change(x<<1,l,mid,tr[x].a,tr[x].b);
else
Change(x<<1|1,mid+1,r,tr[x].a,tr[x].b);
tr[x].a=a,tr[x].b=b,tr[x].minn=Min(tr[x].minn,Min(f(pre[l],a,b),f(pre[r],a,b)));
}
else
{
if(!fr)
Change(x<<1,l,mid,a,b);
else
Change(x<<1|1,mid+1,r,a,b);
}
tr[x].minn=Min(tr[x].minn,Min(tr[x<<1].minn,tr[x<<1|1].minn));
}
inline void change(register int x,register int l,register int r,register int L,register int R,register ll a,register ll b)
{
if(L<=l&&r<=R)
{
Change(x,l,r,a,b);
return;
}
int mid=l+r>>1;
if(L<=mid)
change(x<<1,l,mid,L,R,a,b);
if(R>mid)
change(x<<1|1,mid+1,r,L,R,a,b);
tr[x].minn=Min(tr[x].minn,Min(tr[x<<1].minn,tr[x<<1|1].minn));
}
inline void cal1(register int s,register int t,register ll a,register ll b)
{
int lca=getlca(s,t);
int x=s,y=t;
while(top[x]!=top[lca])
{
change(1,1,n,pl[top[x]],pl[x],-a,a*dis[s]+b);
x=fa[top[x]];
}
change(1,1,n,pl[lca],pl[x],-a,a*dis[s]+b);
while(top[y]!=top[lca])
{
change(1,1,n,pl[top[y]],pl[y],a,dis[s]*a-dis[lca]*2*a+b);
y=fa[top[y]];
}
if(y!=lca)
change(1,1,n,pl[lca]+1,pl[y],a,dis[s]*a-dis[lca]*2*a+b);
}
inline ll query(register int x,register int l,register int r,register int L,register int R)
{
ll res=Min(f(pre[L],tr[x].a,tr[x].b),f(pre[R],tr[x].a,tr[x].b));
if(L==l&&r==R)
return Min(res,tr[x].minn);
int mid=l+r>>1;
if(R<=mid)
return Min(res,query(x<<1,l,mid,L,R));
else if(L>mid)
return Min(res,query(x<<1|1,mid+1,r,L,R));
else
return Min(res,Min(query(x<<1,l,mid,L,mid),query(x<<1|1,mid+1,r,mid+1,R)));
}
inline ll cal2(register int s,register int t)
{
int x=s,y=t;
ll res=inf;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
x^=y^=x^=y;
res=Min(res,query(1,1,n,pl[top[x]],pl[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y])
x^=y^=x^=y;
res=Min(res,query(1,1,n,pl[x],pl[y]));
return res;
}
int main()
{
n=read(),m=read();
for(register int i=1;i<=n-1;++i)
{
int u=read(),v=read();
ll w=read();
add(u,v,w),add(v,u,w);
}
dfs1(1);
dfs2(1,1);
build(1,1,n);
while(m--)
{
int opt=read();
if(opt==1)
{
int s=read(),t=read();
ll a=read(),b=read();
cal1(s,t,a,b);
}
else
{
int s=read(),t=read();
write(cal2(s,t)),puts("");
}
}
return 0;
}

【题解】Luogu P4069 [SDOI2016]游戏的更多相关文章

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

    题面 传送门 题解 如果我们把路径拆成两段,那么这个路径加可以看成是一个一次函数 具体来说,设\(dis_u\)表示节点\(u\)到根节点的距离,那么\((x,lca)\)这条路径上每个节点的权值就会 ...

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

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

  3. Luogu 4069 [SDOI2016]游戏

    BZOJ 4515 树链剖分 + 李超线段树 要求支持区间插入一条线段,然后查询一个区间内的最小值.可以使用李超线段树解决,因为要维护一个区间内的最小值,所以每一个结点再维护一个$res$表示这个区间 ...

  4. 【BZOJ4515】[Sdoi2016]游戏 树链剖分+线段树

    [BZOJ4515][Sdoi2016]游戏 Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 1234567 ...

  5. 4515: [Sdoi2016]游戏

    4515: [Sdoi2016]游戏 链接 分析: 树链剖分 + 超哥线段树.注意细节. 代码: #include<cstdio> #include<algorithm> #i ...

  6. [luogu]P1070 道路游戏[DP]

    [luogu]P1070 道路游戏 题目描述小新正在玩一个简单的电脑游戏.游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针 ...

  7. [Luogu P3825] [NOI2017] 游戏 (2-SAT)

    [Luogu P3825] [NOI2017] 游戏 (2-SAT) 题面 题面较长,略 分析 看到这些约束,应该想到这是类似2-SAT的问题.但是x地图很麻烦,因为k-SAT问题在k>2的时候 ...

  8. [题解] Luogu P5446 [THUPC2018]绿绿和串串

    [题解] Luogu P5446 [THUPC2018]绿绿和串串 ·题目大意 定义一个翻转操作\(f(S_n)\),表示对于一个字符串\(S_n\), 有\(f(S)= \{S_1,S_2,..., ...

  9. 【luogu P1558 色板游戏】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1558 我知道三十棵线段树很暴力,可是我们可以状压啊. 颜色最多30,不会爆int 另外 吐槽评测机 #inc ...

随机推荐

  1. python菜鸟学习心得

    禁忌:学习没精力,就是没精打采.没有热情. 禁忌:学习一半,然后,放在一边. 禁忌:不要东一榔头,西一棒锤. 禁忌:学习要用心. 激情是动力,专注是效率 每次学习都是绕着网络转了一圈.还是要一步一个脚 ...

  2. Servlet(自己实现的Servlet)细节

    Java中无状态的对象就是指某种没用任何属性的仅仅由方法组成的对象. *无状态:无状态方法的好处之一,就是在各种环境下,都可以安全调用.衡量一个方法 是否有状态的,就看它是否改动了其他东西. *有状态 ...

  3. Building gRPC Client iOS Swift Note Taking App

    gRPC is an universal remote procedure call framework developed by Google that has been gaining inter ...

  4. Logstash安装介绍

    前言 logstash是ELK日志系统中的一部分,主要承担将收集完成日志进行过滤,并且输出到es的职责. logstash本身也可以作为客户端部署到应用系统的服务器上进行日志收集,但是由于资源开销占用 ...

  5. C#中string.Format 用法详解

    这篇文章主要介绍了C#中string.format用法,以实例形式较为详细的讲述了string.format格式化的各种用法,非常具有实用价值,需要的朋友可以参考下 本文实例总结了C#中string. ...

  6. FPC导通阻抗计算

    pc线路板是有导电功能的,那么如何仅适用手工计算出线路的阻值能?那么就需要使用到一个公式: W*R*T=6000 W是指铜箔的宽度单位是密耳mil. T是指铜箔厚度单位是盎司oz. R是指铜箔的电阻单 ...

  7. Google Colab Free GPU Tutorial【转载】

    转自:https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d 1.Google Cola ...

  8. 资讯类产品-创业邦APP产品原型模板公开分享

    众所周知,知识付费和资讯是近年来两个受关注度极高的互联网产品方向.18年喜马拉雅“123狂欢节”,3天时间内容消费额4.35亿,足见知识付费内容市场的火爆.字节跳动凭借今日头条APP起家,逐渐跻身互联 ...

  9. ORA-27300 ORA-27301 ORA-27302 sskgpcreates

    1.环境信息 OS:SUSE 12SP3 DB:12.2.0.1.0 2.数据库启动失败 SQL> startup ORA-27154: post/wait create failed ORA- ...

  10. Oracle安装和配置Oracle数据库快速指南

    Oracle安装12C要求参考文档 汇总 中文版:在 Unix AIX,HP-UX,Linux,Solaris 和 MS Windows 操作系统上安装和配置 Oracle 数据库(RDBMS)的要求 ...