zoukankan      html  css  js  c++  java
  • CF 671D Roads in Yusland

    弄完之后点进去一看,竟然是div1的D题……最近真是天天被题虐哭

    推荐这一篇博客 https://www.cnblogs.com/Sakits/p/8085598.html 感觉讲清楚了,也是基本照着这个写的

    一开始题意没有读清楚,这题保证了所以树链都是从下往上的,所以才可以设计dp。

    要把询问映射到树的dfs序上,快速计算子树中的最小值,想到可以使用线段树。

    这个线段树还真是不好写。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N = 5e5 + 5;
    const ll inf = (ll)1 << 60;
    
    int n, m, tot = 0, head[N], dfsc = 0, st[N], ed[N];
    ll f[N];
    vector <int> in[N], out[N];
    
    struct Edge {
        int to, nxt;
    } e[N << 1];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    struct Querys {
        int x, y, pos;
        ll cost;
    } q[N];
    
    bool cmp(const Querys a, const Querys b) {
        return a.pos < b.pos;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0;
        char ch = 0;
        T op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    void dfs(int x, int fat) {
        st[x] = ++dfsc;
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            dfs(y, x);
        }
        ed[x] = dfsc;
    }
    
    inline void chkMin(ll &x, ll y) {
        if(y < x) x = y;
    }
    
    inline ll min(ll x, ll y) {
        return x > y ? y : x;
    }
    
    namespace SegT {
        ll s[N << 2], tag[N << 2];
        
        #define lc p << 1
        #define rc p << 1 | 1
        #define mid ((l + r) >> 1)
        
        inline void up(int p) {
            if(p) s[p] = min(s[lc], s[rc]);
        }
        
        inline void done(int p, ll v) {
            tag[p] = min(inf, tag[p] + v);
            s[p] = min(inf, s[p] + v);
        }
        
        inline void down(int p) {
            if(tag[p] == 0LL) return;
            done(lc, tag[p]), done(rc, tag[p]);
            tag[p] = 0LL;
        }
        
        void build(int p, int l, int r) {
            s[p] = inf, tag[p] = 0LL;
            if(l == r) return;
            
            build(lc, l, mid);
            build(rc, mid + 1, r);
        }
        
        void modifyP(int p, int l, int r, int x, ll v) {
            if(x == l && r == x) {
                s[p] = v;
                return;
            }
            
            down(p);
            if(x <= mid) modifyP(lc, l, mid, x, v);
            else modifyP(rc, mid + 1, r, x, v);
            up(p);
        }
        
        void modify(int p, int l, int r, int x, int y, ll v) {
            if(x > y) return;
            if(x <= l && y >= r) {
                done(p, v);
                return;
            }
            
            down(p);
            if(x <= mid) modify(lc, l, mid, x, y, v);
            if(y > mid) modify(rc, mid + 1, r, x, y, v);
            up(p);
        }
        
        ll query(int p, int l, int r, int x, int y) {
            if(x > y) return inf;
            if(x <= l && y >= r) return s[p];
            down(p);
            ll res = inf;
            if(x <= mid) res = min(res, query(lc, l, mid, x, y));
            if(y > mid) res = min(res, query(rc, mid + 1, r, x, y));
            return res;
        }
        
        #undef mid
        #undef lc
        #undef rc
        
    } using namespace SegT;
    
    inline int bfind(int x) {
        ll ln = 1, rn = m + 1, mid, res;
        for(; ln <= rn; ) {
            mid = (ln + rn) / 2;
            if(q[mid].pos >= x) res = mid, rn = mid - 1;
            else ln = mid + 1;
        }
        return res;
    }   
    
    void solve(int x, int fat) {
        ll sum = 0;
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            solve(y, x);
            sum = min(inf, sum + f[y]);
        }
        
        if(x == 1) {
            f[1] = sum;
            return;
        }
        
        for(unsigned int i = 0; i < in[x].size(); i++)
            modifyP(1, 1, m, in[x][i], min(inf, q[in[x][i]].cost + sum));
        for(unsigned int i = 0; i < out[x].size(); i++)
            modifyP(1, 1, m, out[x][i], inf);
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            modify(1, 1, m, bfind(st[y]), bfind(ed[y] + 1) - 1, sum - f[y]);
        }
        
        f[x] = query(1, 1, m, bfind(st[x]), bfind(ed[x] + 1) - 1);
    }
    
    int main() {
        read(n), read(m);
        build(1, 1, m);
        for(int x, y, i = 1; i < n; i++) {
            read(x), read(y);
            add(x, y), add(y, x);
        }
        dfs(1, 0);
        
        for(int i = 1; i <= m; i++) {
            read(q[i].x), read(q[i].y), read(q[i].cost);
            q[i].pos = st[q[i].x];
        }
        
        sort(q + 1, q + 1 + m, cmp);
        q[m + 1].pos = n + 1;
        
        for(int i = 1; i <= m; i++) 
            in[q[i].x].push_back(i), out[q[i].y].push_back(i);
        
        solve(1, 0);
        
    /*    for(int i = 1; i <= n; i++)
            printf("%lld ", f[i]);
        printf("
    ");   */
        
        if(f[1] >= inf) puts("-1");
        else printf("%lld
    ", f[1]);
        
        return 0;
    }

    感觉还是超过了能力范围……

  • 相关阅读:
    纯CSS实现自动轮播,CSS变量的定义与使用,计算属性的使用
    input:file样式怎样修改
    Div转为Canvas简直不要太好玩~~~
    oracle nvl2函数
    oracle 子查询
    oracle 分组函数执行分析
    oracle外部表
    oracle USING 用法
    面向对象进阶
    面向对象基础
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9468540.html
Copyright © 2011-2022 走看看