zoukankan      html  css  js  c++  java
  • bzoj 3626

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

    让我比较惊讶的一道链剖裸题(' '    ) 做法很精妙

    首先我们考虑对于单个询问时可以拆分成(1, l - 1, z) 和 (1, r, z) 的, 然后考虑对于每一次询问可以表示为将(1, l) 的所有点到根的全部加1 然后求z到根路径的的和。 所以将询问离线, 按询问的l值排序,每一次遇到新的l值就将这一段的点到根的路径全部加1,然后查询即可

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    typedef long long ll;
    const ll maxn = 100001;
    const ll mod = 201314;
    
    ll n, m;
    
    ll int_get() {
        ll x = 0; char c = (char)getchar(); bool f = 0;
        while(!isdigit(c)) {
            if(c == '-') f = 1;
            c = (char)getchar();
        }
        while(isdigit(c)) {
            x = x * 10 + (int)(c - '0');
            c = (char)getchar();
        }
        if(f) x = -x;
        return x;
    }
    
    struct seg {
        ll data, lazy; 
        seg *l, *r;
    }tr[maxn * 3];ll sege = 0;
    seg* root;
    
    void test(seg* x, ll l, ll r) {
        cout << l <<" "<< r <<" "<< x-> data <<" "<< x-> lazy << endl;
        if(l ^ r) {
            ll mid = (l + r) >> 1;
            test(x-> l, l, mid), test(x-> r, mid + 1, r);
        }
    }
    
    seg* build(ll l, ll r) {
        seg* x = tr + sege ++;
        if(l ^ r) {
            ll mid = (l + r) >> 1;
            x-> l = build(l, mid);
            x-> r = build(mid + 1, r);
        }
        return x;
    }
    
    void update(seg* x) {
        if(x-> l) x-> data = x-> l-> data + x-> r-> data;
    }
    
    void pushdown(seg* x, ll l, ll r) {
        if(x-> l && x-> lazy != 0) {
            ll mid = (l + r) >> 1;
            x-> l-> lazy += x-> lazy, x-> l-> data += (mid - l + 1) * x-> lazy;
            x-> r-> lazy += x-> lazy, x-> r-> data += (r - mid) * x-> lazy;
            x-> lazy = 0;
        }
    }
    
    void addlazy(seg* x, ll l, ll r, ll ls, ll rs, ll v) {
        if(l == ls && r == rs) x-> data += v * (rs - ls + 1), x-> lazy += v; 
        else {
            pushdown(x, l, r);
            ll mid = (l + r) >> 1;
            if(rs <= mid) addlazy(x-> l, l, mid, ls, rs, v);
            else if(ls > mid) addlazy(x-> r, mid + 1, r, ls, rs, v);
            else addlazy(x-> l, l, mid, ls, mid, v), addlazy(x-> r, mid + 1, r, mid + 1, rs, v);
            update(x);
        }
    }
    
    ll ask(seg* x, ll l, ll r, ll ls, ll rs) {
        if(l == ls && r == rs) return x-> data;
        else {
            pushdown(x, l, r);
            ll mid = (l + r) >> 1;
            if(rs <= mid) return ask(x-> l, l, mid, ls, rs); 
            else if(ls > mid) return ask(x-> r, mid + 1, r, ls, rs);
            else return ask(x-> l, l, mid, ls, mid) + ask(x-> r, mid + 1, r, mid + 1, rs);
        }
    }
    
    struct edge {
        ll t;
        edge* next;
    }e[maxn * 2], *head[maxn]; ll ne = 0;
    
    void addedge(ll f, ll t) {
        e[ne].t = t, e[ne].next = head[f], head[f] = e + ne ++;
    }
    
    ll h[maxn], size[maxn], fa[maxn], un[maxn], map[maxn], num = 0;
    
    void dfs(ll x, ll pre) {
        fa[x] = pre, size[x] = 1; h[x] = h[pre] + 1;
        for(edge* p = head[x]; p; p = p-> next) {
            if(p-> t != pre) dfs(p-> t, x), size[x] += size[p-> t]; 
        }
    }
    
    void divide(ll x, ll Un) {
        un[x] = Un, map[x] = ++ num;
        if(size[x] == 1) return ;
        ll Max = 0, pos; 
        for(edge* p = head[x]; p; p = p-> next) {
            if(p-> t != fa[x] && size[p-> t] > Max) Max = size[p-> t], pos = p-> t; 
        }
        divide(pos, Un);
        for(edge* p = head[x]; p; p = p-> next) {
            if(p-> t != fa[x] && p-> t != pos) divide(p-> t, p-> t);
        }
    }
    
    void add(ll a, ll b, ll v) {
        ll ls, rs;  
        while(un[a] != un[b]) {
            if(h[un[a]] > h[un[b]]) {
                ls = map[un[a]], rs = map[a];
                addlazy(root, 1, n, ls, rs, v); 
                a = fa[un[a]];
            }
            else {
                ls = map[un[b]], rs = map[b];
                addlazy(root, 1, n, ls, rs, v); 
                b = fa[un[b]];
            } 
        }
        ls = map[a], rs = map[b];
        if(ls > rs) swap(ls, rs);
        addlazy(root, 1, n, ls, rs, v);
    }
    
    ll get(ll a, ll b) {
        ll ret = 0;
        ll ls, rs;
        while(un[a] != un[b]) {
            if(h[un[a]] > h[un[b]]) {
                ls = map[un[a]], rs = map[a];
                ret += ask(root, 1, n, ls, rs);
                a = fa[un[a]];
            }
            else {
                ls = map[un[b]], rs = map[b];
                ret += ask(root, 1, n, ls, rs); 
                b = fa[un[b]];
            }
        }
        ls = map[a], rs = map[b];
        if(ls > rs) swap(ls, rs);
        ret += ask(root, 1, n, ls, rs);
        return ret;
    }
    
    struct block {
        ll x, p, pos, fl;
    }o[maxn]; ll oe = 0;
    
    bool cmp(block a, block b) {
        return a. x < b. x;
    }
    
    ll ans[maxn];
    
    void read() {
        n = int_get(); m = int_get(); 
        for(ll i = 2; i <= n; ++ i) {
            ll u = int_get() + 1;
            addedge(u, i), addedge(i, u);
        }
        for(ll i = 1; i <= m; ++ i) {
            ll a, b, c;
            a = int_get() + 1, b = int_get() + 1, c = int_get() + 1;
            ++ oe, o[oe]. x = a - 1, o[oe]. p = c, o[oe]. pos = i, o[oe]. fl = -1;
            ++ oe, o[oe]. x = b, o[oe]. p = c, o[oe].pos = i, o[oe].fl = 1;
        }
        dfs(1, 0), divide(1, 1);
        root = build(1, n);
    }
    
    void sov() {
        sort(o + 1, o + 1 + oe, cmp); ll pl = 0;
        for(ll i = 1; i <= oe; ++ i) {
            while(pl < o[i]. x) {
                ++ pl; add(1, pl, 1); 
            }
            //test(root, 1, n); cout << endl;
            ans[o[i]. pos] += o[i]. fl * get(1, o[i]. p); 
        }
        for(ll i = 1; i <= m; ++ i) printf("%lld
    ", (ans[i] % mod + mod)% mod);
    }
    
    int main() {
        //freopen("test.in", "r", stdin);
        //freopen("test.out", "w", stdout);
        read(); 
        sov();
        return 0;
    }
    
  • 相关阅读:
    windows2003 iis 配置 php
    ORA16038的解决(日志无法归档)
    ORACLE表连接方式分析及常见用法
    (轉)如何计算Oracle内存中的几个命中率
    SQL調整
    婚后
    Automating Database Startup and Shutdown(开机启动和关闭oracle)
    oracle自动启动与停止
    backgroup process
    改变日期的输出格式(nls_date_format)
  • 原文地址:https://www.cnblogs.com/ianaesthetic/p/4254722.html
Copyright © 2011-2022 走看看