zoukankan      html  css  js  c++  java
  • 【BZOJ 4515】【SDOI 2016 Round1 Day1 T3】游戏

    考场上写了lct,可惜当时对标记永久化的理解并不是十分深刻,导致调一个错误的程序调了4h+,最后这道题爆0了QwQ

    现在写了树链剖分,用标记永久化的线段树维护轻重链,对于$s ightarrow lca$,$lca ightarrow t$分开讨论,把$a×dist+b$这个式子打开,提出常数项,发现是一个一次函数(也不是严格的一次函数,只不过有单调性就可以做了)。标记永久化线段树做一下,每个节点维护一个当前区间的最小值就可以统计答案了233

    这次又手残把“+”打成“*”调了一上午TwT,肉眼对拍大法好!

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int N = 100005;
    const LL inf = 123456789123456789LL;
    void read(int &k) {
    	k = 0; int fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = (k << 1) + (k << 3) + c - '0';
    	k = k * fh;
    }
    
    struct node {
    	int nxt, to, w;
    } E[N << 1];
    int n, m, cnt = 0, point[N], fa[N], top[N], son[N], sz[N], pos[N], wt[N], K[N << 2];
    LL B[N << 2], val[N << 2], di[N], ans;
    bool p[N << 2];
    void ins(int x, int y, int z) {E[++cnt].nxt = point[x]; E[cnt].to = y; E[cnt].w = z; point[x] = cnt;}
    void _(int x) {
    	sz[x] = 1;
    	for(int tmp = point[x]; tmp; tmp = E[tmp].nxt)
    		if (E[tmp].to != fa[x]) {
    			fa[E[tmp].to] = x;
    			di[E[tmp].to] = di[x] + E[tmp].w;
    			_(E[tmp].to);
    			sz[x] += sz[E[tmp].to];
    			if (sz[E[tmp].to] > sz[son[x]]) son[x] = E[tmp].to;
    		}
    }
    void __(int x) {
    	pos[x] = ++cnt; wt[cnt] = x;
    	if (son[x]) {top[son[x]] = top[x]; __(son[x]);}
    	for(int tmp = point[x]; tmp; tmp = E[tmp].nxt)
    		if (E[tmp].to != fa[x] && E[tmp].to != son[x])
    			{top[E[tmp].to] = E[tmp].to; __(E[tmp].to);}
    }
    int LCA(int x, int y) {
    	for(; top[x] != top[y]; x = fa[top[x]])
    		if (di[top[x]] < di[top[y]]) swap(x, y);
    	return di[x] < di[y] ? x : y;
    }
    void pushup(int rt, int l, int r) {
    	if (l < r) val[rt] = min(val[rt << 1], val[rt << 1 | 1]); else val[rt] = inf;
    	if (p[rt]) val[rt] = min(val[rt], min(di[wt[l]] * K[rt], di[wt[r]] * K[rt]) + B[rt]);
    }
    void Build(int rt, int l, int r) {
    	val[rt] = inf;
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	Build(rt << 1, l, mid);
    	Build(rt << 1 | 1, mid + 1, r);
    }
    
    void update(int rt, int l, int r, int a, LL b) {
    	if (!p[rt]) {
    		p[rt] = 1; K[rt] = a; B[rt] = b;
    	} else {
    		LL newl = a * di[wt[l]] + b, newr = a * di[wt[r]] + b, befl = K[rt] * di[wt[l]] + B[rt], befr = K[rt] * di[wt[r]] + B[rt];
    		int mid = (l + r) >> 1;
    		if (newl <= befl && newr <= befr) {
    			K[rt] = a; B[rt] = b;
    		} else
    			if (newl >= befl && newr >= befr)
    				return;
    			else
    				if (a < K[rt]) {
    					double tmp = (b - B[rt]) / (K[rt] - a);
    					if (tmp <= di[wt[mid]]) {
    						update(rt << 1, l, mid, K[rt], B[rt]);
    						K[rt] = a; B[rt] = b;
    					} else
    						update(rt << 1 | 1, mid + 1, r, a, b);
    				} else {
    					double tmp = (B[rt] - b) / (a - K[rt]);
    					if (tmp > di[wt[mid]]) {
    						update(rt << 1 | 1, mid + 1, r, K[rt], B[rt]);
    						K[rt] = a; B[rt] = b;
    					} else
    						update(rt << 1, l, mid, a, b);
    				}
    	}
    	pushup(rt, l, r);
    }
    
    void inc(int rt, int l, int r, int L, int R, int a, LL b) {
    	if (L <= l && r <= R) {update(rt, l, r, a, b); return;}
    	int mid = (l + r) >> 1;
    	if (L <= mid) inc(rt << 1, l, mid, L, R, a, b);
    	if (R > mid) inc(rt << 1 | 1, mid + 1, r, L, R, a, b);
    	pushup(rt, l, r);
    }
    void Q(int rt, int l, int r, int L, int R) {
    	if (L == l && r == R) {ans = min(ans, val[rt]); return;}
    	if (p[rt]) ans = min(ans, min(K[rt] * di[wt[L]], K[rt] * di[wt[R]]) + B[rt]);
    	int mid = (l + r) >> 1;
    	if (R <= mid) Q(rt << 1, l, mid, L, R);
    	else if (L > mid) Q(rt << 1 | 1, mid + 1, r, L, R);
    	else {Q(rt << 1, l, mid, L, mid); Q(rt << 1 | 1, mid + 1, r, mid + 1, R);}
    }
    
    int main() {
    	read(n); read(m); int u, v, e, a, b, lca;
    	for(int i = 1; i < n; ++i) {
    		read(u); read(v); read(e);
    		ins(u, v, e); ins(v, u, e);
    	}
    	
    	_(1);
    	cnt = 0; top[1] = 1;
    	__(1);
    	Build(1, 1, n);
    	
    	LL tmp;
    	for(; m; --m) {
    		read(e);
    		if (e == 1) {
    			read(u); read(v); read(a); read(b);
    			lca = LCA(u, v);
    			tmp = 1LL * a * di[u] + b;
    			for(; top[u] != top[lca]; u = fa[top[u]])
    				inc(1, 1, n, pos[top[u]], pos[u], - a, tmp);
    			inc(1, 1, n, pos[lca], pos[u], - a, tmp);
    			tmp -= (di[lca] << 1) * a;
    			for(; top[v] != top[lca]; v = fa[top[v]])
    				inc(1, 1, n, pos[top[v]], pos[v], a, tmp);
    			inc(1, 1, n, pos[lca], pos[v], a, tmp);
    		} else {
    			ans = inf; read(u); read(v);
    			for(; top[u] != top[v]; u = fa[top[u]]) {
    				if (di[top[u]] < di[top[v]]) swap(u, v);
    				Q(1, 1, n, pos[top[u]], pos[u]);
    			}
    			if (di[u] > di[v]) swap(u, v);
    			Q(1, 1, n, pos[u], pos[v]);
    			printf("%lld
    ", ans);
    		}
    	}
    	return 0;
    }
    

    Round2加油!

  • 相关阅读:
    EF工作流程
    EF简单的CodeFirst示例(自己创建数据库,不使用数据迁移)
    VS2017连接MySQL数据库
    Entity Framework简介
    ADO.NET
    linq连接
    linq语法
    linq和转换运算符
    学习MVC之前必须掌握的c#知识
    java 中 System
  • 原文地址:https://www.cnblogs.com/abclzr/p/5467892.html
Copyright © 2011-2022 走看看