• LWDB


    题意:

    给一棵 $n$ 个节点的树,维护两种操作:

      1.将距离 $x$ $distance leq d$ 的点染成 $c$

      2.询问 $x$ 的颜色。

    解法:

    首先将染色可以转换为每个时间对应一个颜色,问题转化为区间取 $max$

    动态树分治,即可。

    考虑朴素点分治中的每一个重心,将其管辖的所有点按照到重心的距离从大到小排序,然后用线段树维护。

    修改时,从 $x$ 向上走,将每一个重心 $t$ 中 $dist<x,t> + dist<t,y>leq d$ 的点修改。

    查找时,从 $x$ 向上走,查询每一个重心中 $x$ 所对应的值,求 $max$ 即可。

    $O(nlog^2n)$

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    
    #define p E[i].x
    #define N 100010
    #define M 7000010
    #define l(x) ch[x][0]
    #define r(x) ch[x][1]
    #define MP(x, y) make_pair(x, y)
    #define LL long long
    
    using namespace std;
    
    typedef pair<int,int> PII;
    
    struct edge
    {
        int x, to, v;
    }E[N<<1];
    
    int totE, totn, n, m, hev, lef_now;
    int g[N], h[N], de[N], siz[N], root[N], fa[N][21], col[N], d[N];
    int ch[M][2], setv[M];
    vector<PII> nod[N], id[N];
    vector<int> hevs[N];
    int dis[N][21];
    bool v[N];
    
    void addedge(int x, int y, int v)
    {
        E[++totE] = (edge){y, g[x], v}; g[x] = totE;
    }
    
    int build(int l, int r)
    {
        int x = ++totn;
        setv[x] = 0;
        if(l == r) return x;
        int mid = (l+r)>>1;
        l(x) = build(l, mid);
        r(x) = build(mid+1, r);
        return x;
    }
    
    void push(int x)
    {
        if(!setv[x]) return;
        setv[l(x)] = setv[x];
        setv[r(x)] = setv[x];
        setv[x] = 0;
    }
    
    int ask(int x, int l, int r, int qx)
    {
        if(l<r) push(x);
        if(l == r) return setv[x];
        int mid = (l+r)>>1;
        if(qx <= mid) return ask(l(x), l, mid, qx);
        else return ask(r(x), mid+1, r, qx);
    }
    
    void change(int x, int l, int r, int ql, int qr, int qv)
    {
        if(l<r) push(x);
        if(ql<=l && r<=qr)
        {
            setv[x] = qv;
            return;
        }
        int mid=(l+r)>>1;
        if(ql <= mid) change(l(x),l,mid,ql,qr,qv);
        if(mid < qr) change(r(x),mid+1,r,ql,qr,qv);
    }
    
    int dist(int x, int y)
    {
        if(de[x] < de[y]) swap(x, y);
        int ans = 0;
        for(int i = 20;~i;i--)
            if(de[fa[x][i]] >= de[y]) ans += dis[x][i], x = fa[x][i];
        if(x == y) return ans;
        for(int i = 20;~i;i--)
            if(fa[x][i] != fa[y][i])
            {
                ans += dis[x][i]; x = fa[x][i]; 
                ans += dis[y][i]; y = fa[y][i];
            }
        return ans+dis[x][0]+dis[y][0];
    }
    
    void dfs1(int x, int tmp)
    {
        siz[x] = 1;
        h[x] = 0;
        for(int i = g[x];i;i = E[i].to)
            if(!v[p] && p != tmp)
            {
                dfs1(p, x);
                h[x] = max(h[x], siz[p]);
                siz[x] += siz[p];
            }
        h[x] = max(h[x], lef_now - siz[x]);
        if(!hev || h[x] < h[hev]) hev = x;
    }
    
    void dfs(int x)
    {
        for(int i = g[x];i;i = E[i].to)
            if(p != fa[x][0])
            {
                fa[p][0] = x;
                dis[p][0] = E[i].v;
                de[p] = de[x] + 1;
                dfs(p);
            }
    }
    
    void dfs2(int x, int tmp, int now)
    {
        nod[now].push_back(MP(d[x], x));
        for(int i = g[x];i;i = E[i].to)
            if(!v[p] && p != tmp)
            {
                d[p] = d[x] + E[i].v;
                dfs2(p, x, now);
            }
    }
    
    void solve(int x)
    {
        v[x] = 1;
        d[x] = 0;
        dfs2(x, x, x);
        sort(nod[x].begin(), nod[x].end());
        for(int i = 0;i < (int)nod[x].size();i++)
        {
            id[x].push_back( MP(nod[x][i].second, i) );
            hevs[nod[x][i].second].push_back(x);
        }
        sort(id[x].begin(), id[x].end());
        root[x] = build(0, nod[x].size()-1);
        for(int i = g[x];i;i = E[i].to)
            if(!v[p])
            {
                hev = 0;
                lef_now = siz[p];
                dfs1(p, x);
                solve(hev);
            }
    }
    
    int find(int x,int len)
    {
        int l=0,r=nod[x].size()-1;
        while(r-l>4)
        {
            int mid = (l+r)>>1;
            if(nod[x][mid].first <= len) l=mid;
            else r=mid;
        }
        for(int i=r;i>=l;i--)
            if(nod[x][i].first <= len) return i;
        return -1;
    }
    
    void com_change(int x, int len, int v)
    {
        for(int i = 0;i < (int)hevs[x].size();i++)
        {
            int tmp = hevs[x][i];
            int t = find(tmp, len - dist(x, tmp));
            if(t == -1) continue;
            change(root[tmp], 0, id[tmp].size()-1, 0, t, v);
        }
    }
    
    int com_ask(int x)
    {
        int ans = 0;
        for(int i = 0;i < (int)hevs[x].size();i++)
        {
            int tmp = hevs[x][i];
            int t = (*lower_bound(id[tmp].begin(), id[tmp].end(), MP(x, -1))).second;
            ans = max(ans, ask(root[tmp], 0, id[tmp].size()-1, t));
        }
        return col[ans];
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1, x, y, v;i < n;i++)
        {
            scanf("%d %d %d", &x, &y, &v);
            addedge(x, y, v);
            addedge(y, x, v);
        }
        de[1]=1;
        dfs(1);
        for(int j = 1;j <= 20;j++)
        {
            for(int i = 1;i <= n;i++)
            {
                fa[i][j] = fa[fa[i][j-1]][j-1];
                dis[i][j] = dis[fa[i][j-1]][j-1] + dis[i][j-1];
            }
        }
        totn = 0;
        hev = 0;
        lef_now = n;
        dfs1(1, 1);
        solve(hev);
        scanf("%d", &m);
        int x,cmd,len,tot=0;
        while(m--)
        {
            scanf("%d%d",&cmd,&x);
            if(cmd==1)
            {
                scanf("%d%d",&len,&col[++tot]);
                com_change(x,len,tot);
            }
            else printf("%d
    ",com_ask(x));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    flask 日志级别设置只记录error级别及以上的问题
    UnicodeDecodeError: ‘utf-8’ codec can’t decode byte...
    Python 爬虫使用固定代理IP
    python中json报错:json.decoder.JSONDecodeError: Invalid control character at: line 2 column 18 (char 19)
    scrapy中命令介绍
    Python atexit模块
    MP和OMP算法
    如何理解希尔伯特空间
    压缩感知学习博客推荐
    压缩感知系列文章点评
  • 原文地址:https://www.cnblogs.com/lawyer/p/6815033.html
Copyright © 2020-2023  润新知