记录编号 |
587095 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[SDOI 2016 Round1] 游戏 |
最终得分 |
100 |
用户昵称 |
┭┮﹏┭┮ |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
2.661 s |
提交时间 |
2024-03-12 22:14:16 |
内存使用 |
112.62 MiB |
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
//树剖+李超线段树
#define ll long long
const int N = 3e5+10;
const ll inf = 1e17;
int n,m,cnt,num;
struct made{
int ver,nx;ll ed;
}e[N<<1];
int hd[N],tot;
int fa[N],son[N],dep[N],size[N];
int dfn[N],rnk[N],top[N];
ll dis[N];
void add(int x,int y,ll z){
tot++;
e[tot].nx = hd[x],e[tot].ver = y,e[tot].ed = z,hd[x] = tot;
}
void dfs1(int x){
size[x] = 1;
for(int i = hd[x];i;i = e[i].nx){
int y = e[i].ver;
if(dep[y])continue;
dep[y] = dep[x] + 1,fa[y] = x,dis[y] = dis[x] + e[i].ed;
dfs1(y);
size[x] += size[y];
if(!son[x] || size[y] > size[son[x]])son[x] = y;
}
}
void dfs2(int x,int t){
dfn[x] = ++cnt,rnk[cnt] = x;
top[x] = t;
if(!son[x])return;
dfs2(son[x],t);
for(int i = hd[x];i;i = e[i].nx){
int y = e[i].ver;
if(y != fa[x] && y != son[x])dfs2(y,y);
}
}
int LCA(int x,int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])swap(x,y);
x = fa[top[x]];
}
if(dep[x] > dep[y])swap(x,y);
return x;
}
ll k[N],B[N];
struct LiChao_tree{
ll mi[N<<5];int id[N<<5];
void pre(){for(int i = 0;i <= 1e6;i++)mi[i] = 123456789123456789;}
ll get(int x,int i){return k[i] * dis[rnk[x]] + B[i];}
void pushup(int p){mi[p] = min(mi[p],min(mi[p<<1],mi[p<<1|1]));}
void modify(int p,int l,int r,int x){
int mid = l + r >> 1;
if(get(mid,x) < get(mid,id[p]))swap(id[p],x);
mi[p] = min(mi[p],min(get(l,id[p]),get(r,id[p])));
if(get(l,x) < get(l,id[p]))modify(p<<1,l,mid,x);
else if(get(r,x) < get(r,id[p]))modify(p<<1|1,mid+1,r,x);
pushup(p);
}
void modify(int p,int l,int r,int L,int R,int x){
if(L <= l && r <= R)return modify(p,l,r,x),void();
int mid = l + r >> 1;
if(L <= mid)modify(p<<1,l,mid,L,R,x);
if(R > mid)modify(p<<1|1,mid+1,r,L,R,x);
pushup(p);
}
ll query(int p,int l,int r,int L,int R){
if(L <= l && r <= R)return mi[p];
int mid = l + r >> 1;
ll ans = min(get(max(l,L),id[p]),get(min(r,R),id[p]));//!!!
if(L <= mid)ans = min(ans,query(p<<1,l,mid,L,R));
if(R > mid)ans = min(ans,query(p<<1|1,mid+1,r,L,R));
return ans;
}
}t;
void cal(int x,int y){
while(top[x] != top[y]){
t.modify(1,1,n,dfn[top[x]],dfn[x],num);
x = fa[top[x]];
}
t.modify(1,1,n,dfn[y],dfn[x],num);
}
ll calask(int x,int y){
ll ans = 123456789123456789;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])swap(x,y);
ans = min(ans,t.query(1,1,n,dfn[top[x]],dfn[x]));
x = fa[top[x]];
}
if(dep[x] > dep[y])swap(x,y);
ans = min(ans,t.query(1,1,n,dfn[x],dfn[y]));
return ans;
}
int main(){
freopen("menci_game.in","r",stdin);
freopen("menci_game.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1;i < n;i++){
int x,y;ll z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
dep[1] = 1,dfs1(1),dfs2(1,1);
t.pre();B[0] = 123456789123456789;
for(int i = 1;i <= m;i++){
int op,u,v;ll a,b;
scanf("%d%d%d",&op,&u,&v);
if(op == 2)printf("%lld\n",calask(u,v));
else{
scanf("%lld%lld",&a,&b);
int x = LCA(u,v);
k[++num] = -a,B[num] = a * dis[u] + b;
cal(u,x);
k[++num] = a,B[num] = a * (dis[u] - 2 * dis[x]) + b;
cal(v,x);
}
}
return 0;
}