[COGS2278]树黑白

原创 2017年12月19日 11:12:45

这是一题动态点分治qwq
动态点分治就是把原树中的重心拿出来构成了一棵树,然后每个重心记录它的联通块的信息,这样以后修改u就只会影响u到root路径上所有的重心点的信息,查询也可以只用访问u到root路径上所有的重心点。
具体看代码注释吧。。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int num,head[400005],vet[400005],nex[400005],val[400005];
int numl,headl[8000005],root[8000005],son[8000005],nexl[8000005],dis[8000005];
int n,m,s,rt,id,size[200005],f[200005],sum[400005],Num[400005],col[200005];
//num[rt]表示rt的所有子树中黑点数量,sum[rt]表示rt的所有子树中所有黑点到rt的距离之和
bool vis[200005];
void add(int u,int v,int l)
{
    num++;
    vet[num]=v;
    val[num]=l;
    nex[num]=head[u];
    head[u]=num;
}
void addl(int u,int rt,int sontree,int d) //表示u的祖先是rt,u在rt的sontree子树中,和rt距离为d
{
    numl++;
    root[numl]=rt;
    son[numl]=sontree;
    dis[numl]=d;
    nexl[numl]=headl[u];
    headl[u]=numl;
}
void getroot(int u,int fa)//求重心rt
{
    size[u]=1; f[u]=1;
    for (int i=head[u]; i; i=nex[i])
    {
        int v=vet[i];
        if (!vis[v] && v!=fa)
        {
            getroot(v,u);
            size[u]+=size[v];
            f[u]=max(f[u],size[v]);
        }
    }
    f[u]=max(f[u],s-size[u]);
    if (f[u]<f[rt]) rt=u;
}
void build(int u,int fa,int rt,int sontree,int d)//建立新重心树
{
    addl(u,rt,sontree,d);
    for (int i=head[u]; i; i=nex[i])
    {
        int v=vet[i];
        if (!vis[v] && v!=fa) build(v,u,rt,sontree,d+val[i]);
    } 
}
void dfs(int u)
{
    vis[u]=1;
    id++;
    int idu=id;
    addl(u,idu,0,0);
    for (int i=head[u]; i; i=nex[i])
    {
        int v=vet[i];
        if (!vis[v])
        {
            id++;
            build(v,u,idu,id,val[i]);
        }
    }
    for (int i=head[u]; i; i=nex[i])
    {
        int v=vet[i];
        if (!vis[v])
        {
            s=size[v];
            rt=0;
            getroot(v,0);
            dfs(rt);
        }
    }
}
void change(int u)//修改
{
    int ff=-1;
    if (!col[u]) ff=1;
    for (int i=headl[u]; i; i=nexl[i])
    {
        int rt=root[i],sontree=son[i];
        Num[rt]+=ff; sum[rt]+=ff*dis[i];
        if (sontree) Num[sontree]+=ff,sum[sontree]+=ff*dis[i];
    }
    col[u]^=1;
}
int query(int u)
{
    int ans=0;
    for (int i=headl[u]; i; i=nexl[i])
    {
        int rt=root[i],sontree=son[i];
        ans+=dis[i]*(Num[rt]-Num[sontree])+sum[rt]-sum[sontree];
        //u在rt的子树中对答案贡献=u到rt的距离*rt的子树中除了sontree外(u所在子树)所有的黑点的数量+rt的子树除了sontree外所有黑点到rt的距离
    }
    return ans;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1; i<n; i++)
    {
        int u,v,l;
        scanf("%d%d%d",&u,&v,&l);
        add(u,v,l);
        add(v,u,l);
    }
    s=n;
    rt=0;
    f[0]=1e9;
    getroot(1,0);
    dfs(rt);
    for (int i=1; i<=m; i++)
    {
        char ch[10];
        int x;
        scanf("%s%d",ch,&x);
        if (ch[0]=='M') change(x);
        else printf("%d\n",query(x));
    }
}

蒟蒻表示是看了Little_Fairy_MY 的笔记才懂的qwq

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/adorkable_/article/details/78840563

COGS-2278 树黑白(动态树分治)

传送门:COGS-2278 题意:给定一棵树,要求维护以下操作: 1、M u 将u节点反色 2、Q u 查询u到所有黑色节点距离和 题解:动态树分治,更新时判断一下原本是黑色还是白色,是黑色就...
  • qq_31759205
  • qq_31759205
  • 2017-08-14 20:48:59
  • 200

黑白树

问题 B: 黑白树 时间限制: 2 Sec  内存限制: 512 MB 提交: 75  解决: 45 [提交][状态][讨论版] 题目描述 给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两...
  • qq_37759040
  • qq_37759040
  • 2017-07-31 20:58:17
  • 72

JZOJ3745

给初中的讲题,顺便打下练手题,然而发现我已经是老年选手了,平时口胡太多打题会死的。。。竟然把dep打成dfn,本来是区间修改单点查询的线段树,为了常数改成单点修改区间询问,然而我打了单点询问。题目我们...
  • samjia2000
  • samjia2000
  • 2017-04-02 21:31:48
  • 251

foj2204 圆环没有连续7个黑或白的可能数

作为全场难度第三的题目,比赛的时候写出来了。。好高兴。。 枚举开头0的个数(1~6),算出结果*2 #include #include #include #include #define mod 20...
  • cacyth
  • cacyth
  • 2015-10-06 17:16:47
  • 379

[COGS2278]树黑白

这是一题动态点分治qwq 动态点分治就是把原树中的重心拿出来构成了一棵树,然后每个重心记录它的联通块的信息,这样以后修改u就只会影响u到root路径上所有的重心点的信息,查询也可以只用访问u到roo...
  • adorkable_
  • adorkable_
  • 2017-12-19 11:12:45
  • 55

【bzoj3319】【黑白树】【并查集】

Description 给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:     1.查询u到根路径上的第一条黑色边的标号。 2.将u到v    路径上的所有边的颜色设为黑...
  • sunshinezff
  • sunshinezff
  • 2016-05-17 09:04:28
  • 767

[XJOI]黑白树

题目大意有一棵以11为根的nn个点的树,每个点有黑白两种颜色以及一个权值(一开始都是零)。 有qq个操作,有以下两种: ∙ \bullet\ 选定一个点xx,将所有黑色节点yy的权值加上lca(x...
  • a_crazy_czy
  • a_crazy_czy
  • 2017-05-18 20:56:54
  • 593

BZOJ 3319 黑白树 并查集+线段树

题目大意:给定一棵树,有两种操作: 1.询问某个点到根的路径上遇到的第一个黑色边的编号 2.将某条路径涂黑 首先将每条边归到它下面的点上 记录每个点到根路径上深度最大的黑点 那么...
  • PoPoQQQ
  • PoPoQQQ
  • 2015-03-06 19:39:22
  • 1436

COGS-2282 [HZOI 2015]黑树白(树状数组+树链剖分)

2282. [HZOI 2015]黑树白 ★★   输入文件:D_Tree.in   输出文件:D_Tree.out   简单对比 时间限制:3.5 s   内存限制:512 MB 【题...
  • qq_31759205
  • qq_31759205
  • 2017-08-15 23:49:22
  • 156
收藏助手
不良信息举报
您举报文章:[COGS2278]树黑白
举报原因:
原因补充:

(最多只允许输入30个字)