zoukankan      html  css  js  c++  java
  • 「luogu3258」[JLOI2014] 松鼠的新家

    https://www.luogu.org/problemnew/show/P3258

    (树剖裸题


    树上差分 = = 差分 + lca

    1. 树上差分基本思想:和差分一样,用前缀和的思想来处理解(操作后的树上,任意节点的糖果数 是通过所有与其相连的子节点的和 以及该节点在差分数组里的值 得到的(dfs);

    2. 因为这道题并不需要除了lca以外的信息,故tarjan

    对于一组修改u,v :只需修改差分数组 ----- diff[u]++, diff[v], diff[lca(u,v)]--, diff[fa[lca(u,v)]]--

    至于为什么,看1;

    剩下自己想;;

    // 15owzLy1
    //luogu3258.cpp
    //2018 09 25      18:45:43
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    typedef long long ll;
    typedef double db;
    using namespace std;
    
    const int N = 300005;
    struct node {
        int next, to;
    }edge[N<<1];
    int set_[N], candy[N], diff[N], n, head[N], head_q[N], fa[N];
    int query[N][2], a, b, c, cnt;
    bool vis[N];
    
    template<typename T>inline void read(T &x_) {
        x_=0;bool f_=0;char c_=getchar();
        while(c_<'0'||c_>'9'){f_|=(c_=='-');c_=getchar();}
        while(c_>='0'&&c_<='9'){x_=(x_<<1)+(x_<<3)+(c_^48);c_=getchar();}
        x_=f_?-x_:x_;
    }
    
    inline void jb(int u, int v) {
        edge[++cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt;
    }
    
    int get_set_(int x) {
        return (set_[x]==x)?x:set_[x]=get_set_(set_[x]);
    }
    
    inline void Merge(int x, int y) {
        set_[get_set_(y)]=get_set_(x);
    }
    
    void dfs(int u) {
        vis[u]=true;
        for(int i=head[u];i;i=edge[i].next) {
            int v=edge[i].to;
            if(v==fa[u]) continue;
            fa[v]=u;
            dfs(v);
            Merge(u, v);
        }
    
        if(vis[query[u][0]]) {
            a=get_set_(query[u][0]); 
            if(a!=get_set_(u)) {
                diff[a]--, diff[fa[a]]--;
                diff[u]++, diff[query[u][0]]++;
            }
        }
        if(vis[query[u][1]]) {
            a=get_set_(query[u][1]);
            if(a!=get_set_(u)) {
                diff[a]--, diff[fa[a]]--;
                diff[query[u][1]]++, diff[u]++;
            }
        }
    }
    
    void get_ans(int u) {
        candy[u]=diff[u];
        for(int i=head[u];i;i=edge[i].next) {
            int v=edge[i].to;
            if(v==fa[u]) continue;
            get_ans(v);
            candy[u]+=candy[v];
        }
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("luogu3258.in","r",stdin);
        freopen("luogu3258.out","w",stdout);
    #endif
        int x, y, a1;
        read(n); read(x); a1=x;
        for(int i=1;i<n;i++) {
            read(y);
            query[y][0]=x, query[x][1]=y;
            x=y;
        }
    
        for(int i=1;i<n;i++) read(x), read(y), jb(x, y), jb(y, x);
        for(int i=1;i<=n;i++) set_[i]=i;
        dfs(1); get_ans(1); candy[a1]++;
        for(int i=1;i<=n;i++)
            printf("%d
    ", candy[i]-1);
        return 0;
    }
  • 相关阅读:
    (Oracle)取当前日期的最近工作日
    (Oracle)误删oracle表结构恢复
    (Oracle)DDL及其数据泵导入导出(impdp/expdp)
    kettle 连接oracle12c问题解决办法:
    js日历算法
    js设置cookies
    js获取下拉框的value值
    js记住密码
    checkBox的全选与全不选
    select下拉框选中其中一个值
  • 原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/9727106.html
Copyright © 2011-2022 走看看