• [NOIP2018]保卫王国


    倍增写法

    #include <bits/stdc++.h>
    
    #define rep(i, a, b) for (int i = a, i##end = b; i <= i##end; ++i)
    #define per(i, a, b) for (int i = a, i##end = b; i >= i##end; --i)
    #define rep0(i, a) for (int i = 0, i##end = a; i < i##end; ++i)
    #define per0(i, a) for (int i = (int)a-1; ~i; --i)
    #define chkmax(a, b) a = std::max(a, b)
    #define chkmin(a, b) a = std::min(a, b)
    #define x first
    #define y second
    #define pb push_back
    #define mp std::make_pair
    #define enter putchar('
    ')
    
    typedef long long ll;
    
    using std::max;
    using std::swap;
    
    int read() {
    	int w = 0, f = 1; char c;
    	while (!isdigit(c = getchar())) c == '-' && (f == -1);
    	while (isdigit(c)) w = w*10+(c^48), c = getchar();
    	return w * f;
    }
    
    const int N = 100005;
    const ll oo = 1ll<<50;
    
    int n, m, p[N];
    ll sgm = 0;
    
    struct Edge { int v, nxt; } e[N*2];
    int G[N], edges = 0;
    void adde(int u, int v) { e[edges++] = (Edge){v, G[u]}; G[u] = edges-1; }
    
    ll f[2][N], g[2][2][18][N], h[18][N]; int d[N];
    void dfs1(int u, int fa) {
    	for (int i = G[u], v; ~i; i = e[i].nxt) {
    		if ((v = e[i].v) == fa) continue;
    		dfs1(v, u);
    		f[0][u] += max(f[0][v], f[1][v]); f[1][u] += f[0][v];
    	}
    	f[1][u] += p[u];
    }
    void dfs2(int u, int fa) {
    	d[u] = d[h[0][u] = fa]+1;
    	g[0][0][0][u] = g[1][0][0][u] = f[0][fa] - max(f[0][u], f[1][u]);
    	g[0][1][0][u] = f[1][fa] - f[0][u];
    	g[1][1][0][u] = -oo;
    	rep(i, 1, 17) {
    		h[i][u] = h[i-1][h[i-1][u]];
    		g[0][0][i][u] = max(g[0][0][i-1][u]+g[0][0][i-1][h[i-1][u]], g[0][1][i-1][u]+g[1][0][i-1][h[i-1][u]]);
    		g[0][1][i][u] = max(g[0][0][i-1][u]+g[0][1][i-1][h[i-1][u]], g[0][1][i-1][u]+g[1][1][i-1][h[i-1][u]]);
    		g[1][0][i][u] = max(g[1][0][i-1][u]+g[0][0][i-1][h[i-1][u]], g[1][1][i-1][u]+g[1][0][i-1][h[i-1][u]]);
    		g[1][1][i][u] = max(g[1][0][i-1][u]+g[0][1][i-1][h[i-1][u]], g[1][1][i-1][u]+g[1][1][i-1][h[i-1][u]]);
    	}
    	for (int i = G[u]; ~i; i = e[i].nxt)
    		if (e[i].v != fa) dfs2(e[i].v, u);
    }
    
    void jump(ll &f0, ll &f1, int &x, int i) {
    	ll g0 = max(f0+g[0][0][i][x], f1+g[1][0][i][x]), g1 = max(f0+g[0][1][i][x], f1+g[1][1][i][x]);
    	f0 = g0, f1 = g1; x = h[i][x];
    }
    ll dp(int x, int a, int y, int b) {
    	if (d[x] < d[y]) swap(x, y), swap(a, b);
    	ll f0, f1;
    	a ? (f0 = -oo, f1 = f[1][x]) : (f0 = f[0][x], f1 = -oo);
    	for (int i = 0, j = d[x]-d[y]; j; j >>= 1, i++)
    		if (j & 1) jump(f0, f1, x, i);
    	if (x == y) {
    		b ? (f0 = -oo) : (f1 = -oo);
    		for (int i = 0, j = d[x]-1; j; j >>= 1, i++)
    			if (j & 1) jump(f0, f1, x, i);
    		return max(f0, f1);
    	}
    	ll g0, g1;
    	b ? (g0 = -oo, g1 = f[1][y]) : (g0 = f[0][y], g1 = -oo);
    	per0(i, 18)
    		if (h[i][x] != h[i][y])	jump(f0, f1, x, i), jump(g0, g1, y, i);
    	int u = h[0][x]; ll h0 = f[0][u]-max(f[0][x], f[1][x])-max(f[0][y], f[1][y])+max(f0, f1)+max(g0, g1), h1 = f[1][u]-f[0][x]-f[0][y]+f0+g0;
    	for (int i = 0, j = d[u]-1; j; j >>= 1, i++)
    		if (j & 1) jump(h0, h1, u, i);
    	return max(h0, h1);
    }
    
    int main() {
    	n = read(), m = read(); read();
    	rep(i, 1, n) p[i] = read(), sgm += p[i];
    	memset(G, -1, sizeof G);
    	rep(i, 2, n) { int u = read(), v = read(); adde(u, v), adde(v, u); }
    	dfs1(1, 0), dfs2(1, 0);
    	while (m--) {
    		int x = read(), a = read(), y = read(), b = read();
    		ll tot = dp(x, !a, y, !b);
    		printf("%lld
    ", tot < 0 ? -1 : sgm-tot);
    	}
    	return 0;
    }
    

    ddp写法

    这篇代码鸽了
    
  • 相关阅读:
    10 Fresh & Free Bootstrap 5 Admin and Dashboard Templates 2022 辉
    非参数估计:核密度估计KDE 辉
    7个顶级静态代码分析工具 辉
    基于机器学习的用户实体行为分析技术在账号异常检测中的应用 辉
    Docker镜像扫描器的实现 辉
    Kubehunter:一个用于Kubernetes渗透测试的开源工具 辉
    九大顶级静态代码分析工具 辉
    Apache ab压力测试
    Insert into select 批量同步数据
    JVM 逃逸分析 同步缺省 标量替换 栈上分配
  • 原文地址:https://www.cnblogs.com/ac-evil/p/13922966.html
Copyright © 2020-2023  润新知