[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

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

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

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

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

【UER #4】被删除的黑白树

前言首先,星期五晚的网络赛我居然忘了报名。。。。 于是我看了看题,发现我无力回天了。。。。 (星期五晚的主持人大赛好看吗?表示和cty一起做题便基本没看八台大戏了)题目很久很久以前,有一棵树加入了...
  • xieguofu2014
  • xieguofu2014
  • 2015年10月25日 10:51
  • 543

CodeM美团B轮A题 黑白树 【贪心】

题目地址思路 : 题意应该好懂. 思路就是贪心, 每次都去选择叶结点去更新, 因为叶结点始终都会去更新的, 所以我们就贪心的取叶结点去染色, 然后把叶子和它上面k-1个给染了, 继续遍历那k-1个, ...
  • Anxdada
  • Anxdada
  • 2017年06月25日 23:21
  • 212

美团CODEM 黑白树 思维,拓扑DP

时间限制:1秒 空间限制:32768K 一棵n个点的有根树,1号点为根,相邻的两个节点之间的距离为1。树上每个节点i对应一个值k[i]。每个点都有一个颜色,初始的时候所有点都是白色的。 你需要通...
  • just_sort
  • just_sort
  • 2017年06月30日 15:45
  • 139

3319: 黑白树

6
  • Mmh2000
  • Mmh2000
  • 2017年07月24日 21:56
  • 125

四叉树存储2^n大小的图像

#include typedef struct structQTree QTree; struct structQTree {     unsigned char pix...
  • sinapme
  • sinapme
  • 2013年12月17日 16:26
  • 755

图像的四叉树深度优先存储

#include #include "QuadTree.h" #include #include #include #include #include #include #include...
  • sinapme
  • sinapme
  • 2013年12月18日 08:42
  • 580

[XJOI]黑白树

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

XJOI 迷你火车头

题目描述 一列火车有一个火车头拖着一长串的车厢,每个车厢有若干个乘客。一旦火车头出了故障,所有的车厢就只能停在铁轨上了,因此铁路局给每列火车配备了三个迷你火车头,每个迷你火车头可以拖动一定数量的车厢...
  • LOI__DiJiang
  • LOI__DiJiang
  • 2015年11月03日 14:56
  • 482
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[COGS2278]树黑白
举报原因:
原因补充:

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