loj2032 「SDOI2016」游戏

做了 [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
", rangeQuery());
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/8898092.html