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

 
首先树链剖分一下,那么我们只要解决序列的问题就能用乘一个logn的代价解决树上问题了。
我们要支持的两个操作是:
1.在[l,r]区间内添加一条y=kx+b的直线。
2.询问[l,r]区间内所有直线的最小值。
我们考虑使用线段树来维护这些直线,考虑用懒标记在每个节点上标记一条覆盖整个区间的直线。
如果一个节点上已经有一条直线,我们又在上面加上了一条直线,我们应该怎么维护这两条直线的并呢?
计算出两条直线左右端点的值,如果存在一个直线整体在另一条直线上的情况,直接保留最优直线即可。
否则计算两条直线在端点出的函数值,在这个节点保留最优区间长的一条直线,把另一条直线向下传递即可。
对于每个修改操作,[l,r]区间可以拆成logn个节点,每个节点因为每次长度至少减半,所以最多传递logn次,时间复杂度为O(log^2n)。
对于每个询问操作,直接在每个走过的直线和拆成的区间上查询即可,时间复杂度为O(logn)。
然后树上问题随便讨论讨论就行了。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
typedef long long ll;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=100010;
const ll inf=123456789123456789ll;
ll ans,minv[maxn<<2],val[maxn],dist[maxn];
int n,m,first[maxn],next[maxn<<1],to[maxn<<1],dis[maxn<<1],e;
void AddEdge(int w,int v,int u) {
to[++e]=v;dis[e]=w;next[e]=first[u];first[u]=e;
to[++e]=u;dis[e]=w;next[e]=first[v];first[v]=e;
}
int fa[maxn],dep[maxn],son[maxn],siz[maxn];
void dfs(int x) {
dep[x]=dep[fa[x]]+1;siz[x]=1;
ren if(to[i]!=fa[x]) {
fa[to[i]]=x;dist[to[i]]=dist[x]+dis[i];
dfs(to[i]);siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[to[son[x]]]) son[x]=i;
}
}
int top[maxn],pos[maxn],cnt;
void build(int x,int tp) {
top[x]=tp;pos[x]=++cnt;val[cnt]=dist[x];
if(son[x]) build(to[son[x]],tp);
ren if(to[i]!=fa[x]&&i!=son[x]) build(to[i],to[i]);
}
int setv[maxn<<2];
struct Line {
int k;ll b;
ll f(ll x) {return x*k+b;}
}A[maxn<<2];
void query(int o,int l,int r,int ql,int qr) {
if(setv[o]) ans=min(ans,min(A[o].f(val[max(ql,l)]),A[o].f(val[min(qr,r)])));
if(ql<=l&&r<=qr) ans=min(ans,minv[o]);
else {
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(ql<=mid) query(lc,l,mid,ql,qr);
if(qr>mid) query(rc,mid+1,r,ql,qr);
}
}
void maintain(int o,int l,int r) {
int lc=o<<1,rc=lc|1;
if(l<r) minv[o]=min(minv[lc],minv[rc]);
if(setv[o]) minv[o]=min(minv[o],min(A[o].f(val[l]),A[o].f(val[r])));
}
void cover(int o,int l,int r,Line x) {
if(!setv[o]) setv[o]=1,A[o]=x;
else if(l==r) {
if(A[o].f(val[l])>x.f(val[l])) A[o]=x;
}
else {
int mid=l+r>>1,lc=o<<1,rc=lc|1;
ll fl=A[o].f(val[l]),fr=A[o].f(val[r]);
ll gl=x.f(val[l]),gr=x.f(val[r]);
if(fl>=gl&&fr>=gr) A[o]=x;
else if(fl<=gl&&fr<=gr) return;
else {
if(gl<fl) {
if(A[o].f(val[mid])<=x.f(val[mid])) cover(lc,l,mid,x);
else cover(rc,mid+1,r,A[o]),A[o]=x;
}
if(gr<fr) {
if(A[o].f(val[mid+1])<=x.f(val[mid+1])) cover(rc,mid+1,r,x);
else cover(lc,l,mid,A[o]),A[o]=x;
}
}
}
maintain(o,l,r);
}
void update(int o,int l,int r,int ql,int qr,Line x) {
if(ql<=l&&r<=qr) cover(o,l,r,x);
else {
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(ql<=mid) update(lc,l,mid,ql,qr,x);
if(qr>mid) update(rc,mid+1,r,ql,qr,x);
maintain(o,l,r);
}
}
int query(int x,int y,int tp) {
int f1=top[x],f2=top[y];
while(f1!=f2) {
if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
if(tp) query(1,1,n,pos[f1],pos[x]);
x=fa[f1];f1=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
if(tp) query(1,1,n,pos[x],pos[y]);
return x;
}
void update(int x,int z,int k,ll b) {
int f=top[x];
while(f!=top[z]) {
update(1,1,n,pos[f],pos[x],(Line){k,b});
x=fa[f];f=top[x];
}
update(1,1,n,pos[z],pos[x],(Line){k,b});
}
int main() {
n=read();m=read();
rep(i,2,n) AddEdge(read(),read(),read());
dfs(1);build(1,1);
rep(i,1,n*4) minv[i]=inf;
rep(i,1,m) {
int tp=read(),x=read(),y=read();
if(tp==2) {
ans=inf;query(x,y,1);
printf("%lld\n",ans);
}
else {
int a=read(),b=read();
int z=query(x,y,0);
update(x,z,-a,b+dist[x]*a);
update(y,z,a,b+(dist[x]-2*dist[z])*a);
}
}
return 0;
}

  

BZOJ4515: [Sdoi2016]游戏的更多相关文章

  1. [bzoj4515][Sdoi2016]游戏-树链剖分+李超线段树

    Brief Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,A ...

  2. bzoj千题计划276:bzoj4515: [Sdoi2016]游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=4515 把lca带进式子,得到新的式子 然后就是 维护树上一次函数取min 一个调了一下午的错误: 当 ...

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

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

  4. 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][ ...

  5. 4515: [Sdoi2016]游戏

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

  6. bzoj 4515: [Sdoi2016]游戏

    Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,Alice 会 ...

  7. [SDOI2016]游戏

    Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,Alice 会 ...

  8. 【题解】Luogu P4069 [SDOI2016]游戏

    原题传送门 看到这种题,想都不用想,先写一个树链剖分 然后发现修改操作增加的是等差数列,这使我们想到了李超线段树 先进性树剖,然后用李超线段树维护区间最小,这样就做完了(写码很容易出错) 复杂度为\( ...

  9. BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)

    BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...

随机推荐

  1. visual studio2010复制粘贴源代码到Word时乱码问题 分类: C# 2014-11-28 09:25 687人阅读 评论(0) 收藏

    问题描述: visual studio2010 拷贝源代码的时候,在windows自带的写字板和word2010上,粘贴的时候中文字符都会变成乱码. 如: "该用户已经被成功添加" ...

  2. hdu 4041 2011北京赛区网络赛B 搜索 ***

    直接在字符串上搜索,注意逗号的处理 #include<cstdio> #include<iostream> #include<algorithm> #include ...

  3. myeclipse+tomcat 工程名改名的问题 ——————完美解决方案

    当建好的工程再重命名之后,发布和访问的时候都还是原来的名字,这个问题纠结了我很久,最好找到解决方法,这里分享一下,希望大家不要再受这种困惑.解决方法: 点击工程右键->properties-&g ...

  4. BRIEF 特征描述子

    Binary Robust Independent Elementary Features www.cnblogs.com/ronny 1. BRIEF的基本原理 我们已经知道SIFT特征采用了128 ...

  5. 在Visualforce page中用自带的控件实现Ajax回调后台方法(并且可以用js去动态给parameters赋值)

    这里用的组合是:apex:commandLink  + apex:actionFunction + apex:outputPanel 这里的 apex:commandLink 和 apex:actio ...

  6. barabasilab-networkScience学习笔记6-evolving networks

    第一次接触复杂性科学是在一本叫think complexity的书上,Allen博士很好的讲述了数据结构与复杂性科学,barabasi是一个知名的复杂性网络科学家,barabasilab则是他所主导的 ...

  7. canvas加载进度条

    <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content=& ...

  8. filter应用案例一:分IP统计访问次数

    统计工作需要在所有资源之前都执行,那么就可以放到Filter中了.用Map<String,Integer>装载统计的数据.Map创建时间(使用ServletContextListener, ...

  9. 廖雪峰js教程笔记4 sort排序的一些坑

    排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个对象呢?直接比较数学上的大小是没有意义的,因 ...

  10. Codeforces Round #375 (Div. 2) - A

    题目链接:http://codeforces.com/contest/723/problem/A 题意:在一维坐标下有3个人(坐标点).他们想选一个点使得他们3个到这个点的距离之和最小. 思路:水题. ...