• 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;
    }
    
  • 相关阅读:
    Python DB API 连接数据库
    PHP base64多图片上传
    Linux vim编写程序时出现高亮字符,如何取消?
    CDN,内容分发网络。
    MySQL随机取数据
    tp5 快速接入扫码支付
    tp5定时器
    清空测试数据
    Centos Crontab查看状态和开启
    select2 使用
  • 原文地址:https://www.cnblogs.com/poorpool/p/8898092.html
Copyright © 2020-2023  润新知