zoukankan      html  css  js  c++  java
  • CF932F(李超线段树+dp)

    CF932F(李超线段树+dp)

    此题又是新玩法, 李超线段树合并优化(dp)

    一个显然的(Theta(n^2)dp): (dp[x])表示从x出发到叶子节点的最小代价

    (dp[x] = min(dp[y] + a[x] * b[y]) ~~(y in subtree(x)))

    如果我们将(b[y])看成斜率, (dp[y])看成纵截距, (a[x])看成横坐标, 那么问题转为了在平面上有一些直线, 选出与直线(x = a[x])相交的最靠下的点吗, 李超线段树板题, 但这道题出到了树上所以要用上线段树合并 因为有负数所以要整体右移一下, 相应的直线也需变换, 具体见代码

    代码:

    #pragma GCC optimize(3)
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define re register
    #define ll long long
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        x = 0; bool f = 0;
        char c = getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
        for (;isdigit(c);c=getchar()) x=x*10+(c^48);
        if (f) x=-x;
    }
    
    template <typename T>
    void write(T x) {
        if (x < 0) putchar('-'), x = -x;
        if (x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    
    const int N = 200500;
    const int Delta = 100005;
    const int Len = Delta << 1;
    
    
    int h[N], ne[N<<1], to[N<<1];
    int T[N], tot, cnt;
    inline void add(int x, int y) {
    	ne[++tot] = h[x], to[tot] = y, h[x] = tot;
    }
    
    int ls[N<<5], rs[N<<5], p[N<<5];
    ll n, ans[N], a[N], b[N];
    struct node {
    	ll k, b;
    }line[N];
    
    inline ll calc(int num, ll x) {
    	return line[num].k * x + line[num].b;
    }
    
    void insert(int &x, int l, int r, int num) {
    	if (!x) return x = ++cnt, p[x] = num, void();
    	int mid = (l + r) >> 1;
    	if (calc(p[x], mid) > calc(num, mid)) swap(p[x], num);
    	if (calc(p[x], l) <= calc(num, l) && 
    		calc(p[x], r) <= calc(num, r)) return;
    	if (calc(p[x], l) > calc(num, l)) insert(ls[x], l, mid, num);
    	else insert(rs[x], mid + 1, r, num);
    }
    
    const ll INF = 0x7fffffffffff;
    ll query(int now, int l, int r, ll x) {
    	if (!now) return INF;
    	int mid = (l + r) >> 1;
    	return min(calc(p[now], x), x <= mid ?
    		query(ls[now], l, mid, x) : query(rs[now], mid + 1, r, x));
    }
    
    int merge(int x, int y, int l, int r) {
    	if (!x || !y) return x | y;
    	insert(x, l, r, p[y]);
    	int mid = (l + r) >> 1;
    	ls[x] = merge(ls[x], ls[y], l, mid);
    	rs[x] = merge(rs[x], rs[y], mid + 1, r);
    	return x;
    }
    
    void dfs(int x, int fa) {
    	for (re int i = h[x], y; i; i = ne[i]) {
    		if ((y = to[i]) == fa) continue;
    		dfs(y, x); 
    		T[x] = merge(T[x], T[y], 1, Len);
    	}
    	ans[x] = query(T[x], 1, Len, a[x] + Delta);
    	if (ans[x] == INF) ans[x] = 0;
    	line[x] = (node){b[x], ans[x] - b[x] * Delta}; 
    	insert(T[x], 1, Len, x);
    }
    
    int main() {
    	read(n);
    	for (re int i = 1;i <= n; i++) read(a[i]);
    	for (re int j = 1;j <= n; j++) read(b[j]);
    	for (re int i = 1;i < n; i++) {
    		int x, y; read(x), read(y);
    		add(x, y), add(y, x);
    	} dfs(1, 0);
    	for (re int i = 1;i <= n; i++) 
    		write(ans[i]), putchar(' ');
    	return 0;
    }
    
  • 相关阅读:
    linux基础
    spring学习 之 spring与java web整合原理示例
    idea 使用tomcat插件创建Java web项目
    xml解析
    spring注解学习之 九 DeferredImportSelector接口
    springboot学习一 idea配置文件乱码
    "从客户端中检测到有潜在危险的 Request.Form 值"的解决方案汇总
    通过Cookie存放用户登录信息以及安全性问题
    从数据库所有表中查找特定的数据(模糊匹配)
    CentOS 7 系列修改默认网卡名为 eth0 的两种方法
  • 原文地址:https://www.cnblogs.com/Hs-black/p/12271622.html
Copyright © 2011-2022 走看看