做了 [JSOI2008]Blue Mary开公司 以后发现这 tm 不就是个傻逼树剖+李超线段树吗,做了以后发现我才是傻逼……树剖竟然写错了……这题是我目前写过最长的代码了qwq

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, uu, vv, ww, dep[100005], fa[100005], dfn[100005], son[100005], siz[100005];
int top[100005], idx, dui[100005], opt, ss, tt, cnt, hea[100005];
ll dis[100005];
const ll oo=123456789123456789;
struct Edge{
int too, nxt, val;
}edge[200005];
struct SGT{
ll val[400005], vak[400005], bva[400005];
bool vis[400005];
void pushUp(int o, int lson, int rson){
val[o] = min(val[o], min(val[lson], val[rson]));
}
void build(int o, int l, int r){
val[o] = oo;
if(l==r) ;
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
if(l<=mid) build(lson, l, mid);
if(mid<r) build(rson, mid+1, r);
}
}
void updateLichao(int o, int l, int r, ll k, ll b){
ll lvalnow=k*dis[dui[l]]+b;
ll rvalnow=k*dis[dui[r]]+b;
ll lvalpre=vak[o]*dis[dui[l]]+bva[o];
ll rvalpre=vak[o]*dis[dui[r]]+bva[o];
if(!vis[o]){
vis[o] = true;
vak[o] = k; bva[o] = b;
val[o] = min(val[o], min(lvalnow, rvalnow));
return ;
}
else if(lvalnow>=lvalpre && rvalnow>=rvalpre) return ;
else if(lvalnow<lvalpre && rvalnow<rvalpre){
val[o] = min(val[o], min(lvalnow, rvalnow));
vak[o] = k;
bva[o] = b;
}
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
ll mvalnow=k*dis[dui[mid]]+b;
ll mvalpre=vak[o]*dis[dui[mid]]+bva[o];
if(lvalnow>=lvalpre){
if(mvalnow>=mvalpre) updateLichao(rson, mid+1, r, k, b);
else{
updateLichao(lson, l, mid, vak[o], bva[o]);
vak[o] = k;
bva[o] = b;
val[o] = min(val[o], min(lvalnow, rvalnow));
}
}
else{
if(mvalnow>=mvalpre) updateLichao(lson, l, mid, k, b);
else{
updateLichao(rson, mid+1, r, vak[o], bva[o]);
vak[o] = k;
bva[o] = b;
val[o] = min(val[o], min(lvalnow, rvalnow));
}
}
pushUp(o, lson, rson);
}
}
void update(int o, int l, int r, int x, int y, ll k, ll b){
if(l>=x && r<=y)
updateLichao(o, l, r, k, b);
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
if(x<=mid) update(lson, l, mid, x, y, k, b);
if(mid<y) update(rson, mid+1, r, x, y, k, b);
pushUp(o, lson, rson);
}
}
ll query(int o, int l, int r, int x, int y){
if(l>=x && r<=y) return val[o];
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
ll re=oo;
if(vis[o]) re = min(re, min(vak[o]*dis[dui[max(l,x)]]+bva[o], vak[o]*dis[dui[min(r,y)]]+bva[o]));
if(x<=mid) re = min(re, query(lson, l, mid, x, y));
if(mid<y) re = min(re, query(rson, mid+1, r, x, y));
return re;
}
}
}sgt;
void add_edge(int fro, int too, int val){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
edge[cnt].val = val;
hea[fro] = cnt;
}
void dfs1(int x, int f, ll p){
dep[x] = dep[f] + 1;
dis[x] = p;
fa[x] = f;
siz[x] = 1;
int maxSon=-1;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=f){
dfs1(t, x, p+edge[i].val);
siz[x] += siz[t];
if(siz[t]>maxSon){
son[x] = t;
maxSon = siz[t];
}
}
}
}
void dfs2(int x, int topf){
dfn[x] = ++idx;
top[x] = topf;
dui[idx] = x;
if(!son[x]) return ;
dfs2(son[x], topf);
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=fa[x] && t!=son[x])
dfs2(t, t);
}
}
int getLca(int u, int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
if(dep[u]>dep[v]) swap(u, v);
return u;
}
void rangeUpdate(){
int lca=getLca(ss, tt);
int x=ss;
ll nb=uu*dis[x]+vv;
ll nk=-uu;
while(top[x]!=top[lca]){
sgt.update(1, 1, n, dfn[top[x]], dfn[x], nk, nb);
x = fa[top[x]];
}
sgt.update(1, 1, n, dfn[lca], dfn[x], nk, nb);
nb = uu*(dis[ss]-dis[lca]-dis[lca])+vv;
nk = uu;
x = tt;
while(top[x]!=top[lca]){
sgt.update(1, 1, n, dfn[top[x]], dfn[x], nk, nb);
x = fa[top[x]];
}
sgt.update(1, 1, n, dfn[lca], dfn[x], nk, nb);
}
ll rangeQuery(){
ll re=oo;
while(top[ss]!=top[tt]){
if(dep[top[ss]]<dep[top[tt]]) swap(ss, tt);
re = min(re, sgt.query(1, 1, n, dfn[top[ss]], dfn[ss]));
ss = fa[top[ss]];
}
if(dep[ss]>dep[tt]) swap(ss, tt);
re = min(re, sgt.query(1, 1, n, dfn[ss], dfn[tt]));
return re;
}
int main(){
cin>>n>>m;
for(int i=1; i<n; i++){
scanf("%d %d %d", &uu, &vv, &ww);
add_edge(uu, vv, ww);
add_edge(vv, uu, ww);
}
dfs1(1, 0, 0);
dfs2(1, 1);
sgt.build(1, 1, n);
while(m--){
scanf("%d", &opt);
if(opt==1){
scanf("%d %d %d %d", &ss, &tt, &uu, &vv);
rangeUpdate();
}
else{
scanf("%d %d", &ss, &tt);
printf("%lld\n", rangeQuery());
}
}
return 0;
}

loj2032 「SDOI2016」游戏的更多相关文章

  1. 【LOJ】#2032. 「SDOI2016」游戏

    题解 看错题了,以为单次修改相当于一个覆盖,后来才明白"添加"-- 就相当于添加很多线段求最小值 首先这个等差数列添加的方式比较烦人,我们拆开两条链,一条s到lca,一条lca到t ...

  2. LOJ_2305_「NOI2017」游戏 _2-sat

    LOJ_2305_「NOI2017」游戏 _2-sat 题意: 给你一个长度为n的字符串S,其中第i个字符为a表示第i个地图只能用B,C两种赛车,为b表示第i个地图只能用A,C两种赛车,为c表示第i个 ...

  3. 「SDOI2016」储能表(数位dp)

    「SDOI2016」储能表(数位dp) 神仙数位 \(dp\) 系列 可能我做题做得少 \(QAQ\) \(f[i][0/1][0/1][0/1]\) 表示第 \(i\) 位 \(n\) 是否到达上界 ...

  4. 「HNOI2018」游戏

    「HNOI2018」游戏 解题思路 首先没有锁上的门可以缩点缩掉,然后对于一扇锁上的门,如果钥匙在左边,那么右边就永远不可能到达左边,同理如果钥匙在右边,左边就永远不可能到达右边. 然后考虑一个暴力的 ...

  5. 「NOI2017」游戏

    「NOI2017」游戏 题目描述 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 \(A\).\(B\).\ ...

  6. loj #2305. 「NOI2017」游戏

    #2305. 「NOI2017」游戏 题目描述 小 L 计划进行 nnn 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 AAA.BBB. ...

  7. LOJ2305 「NOI2017」游戏

    「NOI2017」游戏 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行$n$场 ...

  8. [LOJ 2070] 「SDOI2016」平凡的骰子

    [LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...

  9. liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组

    #2033. 「SDOI2016」生成魔咒     题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...

随机推荐

  1. NodeJS学习视频

    腾讯课堂初级课程 https://ke.qq.com/webcourse/index.html#course_id=196698&term_id=100233129&taid=1064 ...

  2. 滚动条美化插件 nicescroll

    这个插件使用起来非常简单,首先下载插件jquery.nicescroll.min.js 然后在页面中引入jquery,再引入这个插件, 然后在页面中需要修改滚动条的地方,例如id为box的div &l ...

  3. 【转】monkey实战--测试步骤、常用参数、常规monkey命令

    monkey实战--测试步骤.常用参数.常规monkey命令   简要步骤:adb devices---了解包名--adb shell monkey -p 包名 -v 运行次数(多个参数的组合形成不同 ...

  4. html 获取和写入cookie的 方法

    //取Cookie的值            function getCookie(cookie_name) {     var allcookies = document.cookie;     v ...

  5. CodeForces 48C D - The Race (Fraction,数学)

    每个加油的站可以确定一个alpha的上下界,比如,第i次加油站a[i],前面加了i次油,a[i]*10≤ alpha*i <(a[i]+1)*10. 取最大的下界,取最小的上界,看看两者之间的满 ...

  6. UVA 1611 Crane 起重机 (子问题)

    题意:给一个1~n排列,1<=n<=10000,每次操作选取一个长度为偶数的连续区间.交换前一半和后一半,使它变成升序. 题解:每次只要把最小的移动到最左边,那么问题规模就缩小了.假设当前 ...

  7. python面试笔试题汇总

    Python面试攻略(嗨谈篇) 110道python面试笔试题汇总,你能答对几道? Python 面试问答 Top 25 2018 年最常见的 Python 面试题 & 答案

  8. 超全面Java 面试题(2.1)

    这部分主要是开源JavaEE框架方面的内容,包括hibernate.MyBatis.spring.Spring MVC等,由于Struts2已经是明日黄花,在这里就不讨论Struts2的面试题,此外, ...

  9. 【转】JavaScript 节点操作 以及DOMDocument属性和方法

    最近发现DOMDocument对象很重要,还有XMLHTTP也很重要 注意大小写一定不能弄错. 属性: 1Attributes 存储节点的属性列表(只读) 2childNodes 存储节点的子节点列表 ...

  10. 使用jquery.ajax实现省市的二级联动(SSH架构)

    首先实现jquery ajax的二级联动 要下载个jquery.js 我在这里就不准备了 自行百度下载 背景介绍:通过部门的ID来查找部门下的所有班级 我实现二级联动的思路是:先查询所有部门 显示在页 ...