zoukankan      html  css  js  c++  java
  • bzoj 4515: 游戏 树链剖分+线段树

    题目大意:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4515

    题解:

    先让我%一发lych大佬点我去看dalao的题解
    讲的很详细.
    这里纠正一个地方,lych大佬的式子中有一个(a*(d[s]-d[x])+b=-a*d[x]+(b-a*d[s]))
    应该是(a*(d[s]-d[x])+b = -a*d[x] + (b+a*d[s]))
    看来是大爷敲式子的时候敲错了...
    除去这个就很完美啦
    新get了线段树标记永久化的姿势

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const ll maxn = 210010;
    const ll inf = 123456789123456789LL;
    struct Edge{
    	ll to,next;
    	ll dis;
    }G[maxn<<1];
    ll head[maxn],cnt;
    void add(ll u,ll v,ll d){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	head[u] = cnt;
    	G[cnt].dis = d;
    }
    ll son[maxn],siz[maxn],fa[maxn],top[maxn];
    ll dfn[maxn],dfs_clock,num[maxn],dep[maxn];
    ll d[maxn];
    #define v G[i].to
    void dfs(ll u){
    	siz[u] = 1;
    	for(ll i = head[u];i;i=G[i].next){
    		if(v == fa[u]) continue;
    		fa[v] = u;
    		d[v] = d[u] + G[i].dis;
    		dep[v] = dep[u] + 1;
    		dfs(v);
    		siz[u] += siz[v];
    		if(siz[son[u]] < siz[v]) son[u] = v;
    	}
    }
    void dfs(ll u,ll tp){
    	top[u] = tp;
    	dfn[u] = ++dfs_clock;
    	num[dfs_clock] = u;
    	if(son[u]) dfs(son[u],tp);
    	for(ll i = head[u];i;i=G[i].next){
    		if(v == fa[u] || v == son[u]) continue;
    		dfs(v,v);
    	}
    }
    #undef v
    struct Node{
    	ll k,b,minn;
    	bool lazy;
    	Node(){k=lazy=0;b = minn = inf;}
    }T[maxn<<2];
    ll K,B,L,R;ll n;
    ll query(ll rt,ll l,ll r){
    	if(L <= l && r <= R) return T[rt].minn;
    	ll ret = inf;
    	if(T[rt].lazy) ret = min(T[rt].k*d[num[max(L,l)]],T[rt].k*d[num[min(R,r)]]) + T[rt].b;
    	ll mid = l+r >> 1;
    	if(L <= mid) ret = min(ret,query(rt<<1,l,mid));
    	if(R >  mid) ret = min(ret,query(rt<<1|1,mid+1,r));
    	return ret;
    }
    inline ll query(ll l,ll r){
    	if(l > r) swap(l,r);
    	L = l;R = r;
    
    	return query(1,1,n);
    }
    void update(ll rt,ll l,ll r,ll K,ll B){
    	if(T[rt].lazy == 0){
    		T[rt].k = K;T[rt].b = B;T[rt].lazy = 1;
    		if(l < r) T[rt].minn = min(T[rt<<1].minn,T[rt<<1|1].minn);
    		T[rt].minn = min(T[rt].minn,min(T[rt].k*d[num[l]],T[rt].k*d[num[r]])+T[rt].b);
    		return;
    	}
    	ll mid = l+r >> 1;
    	ll y1 = K*d[num[r]] + B;
    	ll y2 = T[rt].k*d[num[r]] + T[rt].b;
    	ll y3 = K*d[num[l]] + B;
    	ll y4 = T[rt].k*d[num[l]] + T[rt].b;
    	if(y3 <= y4 && y1 <= y2) T[rt].k = K,T[rt].b = B;
    	else if(y3 >= y4 && y1 >= y2) return;
    	else if(T[rt].k > K){
    		ll x = (B-T[rt].b)/(T[rt].k-K) + 1;
    		if(x <= d[num[mid]]){
    			swap(T[rt].b,B);swap(T[rt].k,K);
    			update(rt<<1,l,mid,K,B);
    		}else update(rt<<1|1,mid+1,r,K,B);
    	}else{
    		ll x = (T[rt].b - B - 1)/(K - T[rt].k);
    		if(x > d[num[mid]]){
    			swap(T[rt].b,B);swap(T[rt].k,K);
    			update(rt<<1|1,mid+1,r,K,B);
    		}else update(rt<<1,l,mid,K,B);
    	}
    	if(l < r) T[rt].minn = min(T[rt<<1].minn,T[rt<<1|1].minn);
    	if(T[rt].lazy) T[rt].minn = min(T[rt].minn,
    		min(T[rt].k*d[num[l]],T[rt].k*d[num[r]])+T[rt].b);
    }
    void ins(ll rt,ll l,ll r){
    	if(L <= l && r <= R){
    		update(rt,l,r,K,B);return;
    	}
    	ll mid = l+r >> 1;
    	if(L <= mid) ins(rt<<1,l,mid);
    	if(R >  mid) ins(rt<<1|1,mid+1,r);
    	T[rt].minn = min(T[rt<<1].minn,T[rt<<1|1].minn);
    	if(T[rt].lazy) T[rt].minn = min(T[rt].minn,
    		min(T[rt].k*d[num[l]],T[rt].k*d[num[r]])+T[rt].b);
    }
    inline void ins(ll l,ll r){
    	if(l > r) swap(l,r);
    	L=l;R=r;ins(1,1,n);
    }
    inline ll lca(ll u,ll v){
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]]) swap(u,v);
    		u = fa[top[u]];
    	}return dep[u] < dep[v] ? u : v;
    }
    inline void insert(ll u,ll v,ll a,ll b){
    	ll rt = lca(u,v);
    	K = -a;B = b+a*d[u];
    	while(top[u] != top[rt]){
    		ins(dfn[top[u]],dfn[u]);
    		u = fa[top[u]];
    	}ins(dfn[rt],dfn[u]);
    	K = a;B -= (d[rt]<<1)*a;
    	while(top[v] != top[rt]){
    		ins(dfn[top[v]],dfn[v]);
    		v = fa[top[v]];
    	}ins(dfn[rt],dfn[v]);
    }
    inline ll query_all(ll u,ll v){
    	ll ret = inf;
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]]) swap(u,v);
    		ret = min(ret,query(dfn[top[u]],dfn[u]));
    		u = fa[top[u]];
    	}if(dep[u] < dep[v]) swap(u,v);
    	ret = min(ret,query(dfn[v],dfn[u]));
    	return ret;
    }
    int main(){
    	ll m;read(n);read(m);
    	for(ll i=1,u,v;i<n;++i){ll d;
    		read(u);read(v);read(d);
    		add(u,v,d);add(v,u,d);
    	}dfs(1);dfs(1,1);
    	ll op,s,t;ll a,b;
    	while(m--){
    		read(op);read(s);read(t);
    		if(op == 1){
    			read(a);read(b);
    			insert(s,t,a,b);
    		}else{
    			printf("%lld
    ",query_all(s,t));
    		}
    	}
    	getchar();getchar();
    	return 0;
    }
    

    我能说我从昨天下午调到了今天上午,调了6个小时吗?

  • 相关阅读:
    Spring用代码来读取properties文件
    单链表与双链表的区别
    为什么有些IP无法PING通但又能访问
    使用iperf3调试网络
    arm linux 移植 iperf3
    ZYNQ:PetaLinux工程更新HDF文件的脚本
    ZYNQ:使用PetaLinux打包 BOOT.BIN、image.ub
    ZYNQ:提取PetaLinux中Linux和UBoot配置、源码
    ZYNQ:使用 PetaLinux 构建Linux项目
    ZYNQ:使用SDK打包BOOT.BIN、烧录BOOT.BIN到QSPI-FLASH
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6412231.html
Copyright © 2011-2022 走看看