bzoj4154

kdtree

转换一下,看成点,第一位dfs序,第二维深度,那么满足在子树内dfs序限制,然后kdtree上打标记就行了。

 
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, mod = 1e9 + 7;
int rd()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
int n, c, q, root, d, dfs_clock;
int dep[N], in[N], out[N];
vector<int> G[N];
struct data {
    int lc, rc, c, tag, p[2], mx[2], mn[2];
    bool friend operator < (const data &a, const data &b) {
        return a.p[d] == b.p[d] ? a.p[d ^ 1] < b.p[d ^ 1] : a.p[d] < b.p[d];
    }
} a[N];
void update(int x)
{
    int lc = a[x].lc, rc = a[x].rc;
    for(int i = 0; i < 2; ++i) 
    {
        a[x].mn[i] = min(a[x].p[i], min(a[lc].mn[i], a[rc].mn[i]));
        a[x].mx[i] = max(a[x].p[i], max(a[lc].mx[i], a[rc].mx[i]));
    }
}
int build(int l, int r, int D)
{
    if(l > r) return 0;
    d = D;
    int mid = (l + r) >> 1;
    nth_element(a + l, a + mid, a + r + 1);
    a[mid].lc = build(l, mid - 1, D ^ 1);
    a[mid].rc = build(mid + 1, r, D ^ 1);
    a[mid].c = 1;
    a[mid].tag = 0;
    update(mid);
    return mid;
}
void pushdown(int x)
{
    if(!a[x].tag) return;
    int lc = a[x].lc, rc = a[x].rc;
    if(lc) a[lc].tag = a[lc].c = a[x].tag;
    if(rc) a[rc].tag = a[rc].c = a[x].tag;
    a[x].tag = 0;
}
bool In(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2)
{
    return X1 >= x1 && Y1 >= y1 && X2 <= x2 && Y2 <= y2; 
}
bool Out(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2)
{
    return x1 > X2 || x2 < X1 || y1 > Y2 || y2 < Y1;
}
int query(int k, int x, int y)
{
    if(!k || Out(x, y, x, y, a[k].mn[0], a[k].mn[1], a[k].mx[0], a[k].mx[1])) return 0;
    pushdown(k);
    if(x == a[k].p[0] && y == a[k].p[1]) return a[k].c;
    return query(a[k].lc, x, y) + query(a[k].rc, x, y);
}
void modify(int k, int x1, int y1, int x2, int y2, int c)
{
    if(!k || Out(x1, y1, x2, y2, a[k].mn[0], a[k].mn[1], a[k].mx[0], a[k].mx[1])) return;
    pushdown(k);
    if(In(x1, y1, x2, y2, a[k].mn[0], a[k].mn[1], a[k].mx[0], a[k].mx[1])) 
    {
        a[k].tag = a[k].c = c;
        return; 
    }
    if(In(x1, y1, x2, y2, a[k].p[0], a[k].p[1], a[k].p[0], a[k].p[1])) a[k].c = c;
    modify(a[k].lc, x1, y1, x2, y2, c);
    modify(a[k].rc, x1, y1, x2, y2, c);
}
void dfs(int u)
{
    a[u].p[0] = a[u].mn[0] = a[u].mx[0] = dep[u];
    a[u].p[1] = a[u].mn[1] = a[u].mx[1] = in[u] = ++dfs_clock;
    a[u].lc = a[u].rc = 0;
    for(int i = 0; i < G[u].size(); ++i) 
    {
        dep[G[u][i]] = dep[u] + 1;
        dfs(G[u][i]);
    }
    out[u] = dfs_clock;
}
int main()
{
    for(int i = 0; i < 2; ++i)
        a[0].mn[i] = 1e9,
        a[0].mx[i] = -1e9;
    int T = rd();
    while(T--)
    {
        long long ans = 0;
        n = rd();
        c = rd();
        q = rd();
        for(int i = 1; i <= n; ++i) G[i].clear();
        for(int i = 2; i <= n; ++i)
        {
            int fa = rd();
            G[fa].push_back(i);
        }
        dep[1] = 1;
        dfs(1);
        root = build(1, n, 0);
        for(long long i = 1; i <= q; ++i)
        {
            int a = rd(), l = rd(), c = rd();
            int dd = query(root, in[a], dep[a]);
            if(c == 0) ans = (ans + (long long)query(root, dep[a], in[a]) * i) % mod;
            if(c > 0) modify(root, dep[a], in[a], min(dep[a] + l, n), out[a], c);             
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2017-11-23 00:33  19992147  阅读(172)  评论(0编辑  收藏  举报