CF1923E Count Paths

点分治模板题。

假设当前处理的树根为 \(x\),我们考虑如何统计经过点 \(x\) 的合法路径。

\(1\):存在一个与 \(x\) 颜色相同的点,且这个点到 \(x\) 的路径上没有与之颜色相同的点,那么这个点和 \(x\) 就构成了一条合法路径。

\(2\):存在一个与 \(x\) 颜色不相同的点,且这个点到 \(x\) 的路径上没有与之颜色相同的点。那么这个点与 \(x\) 的其他子树中与之颜色相同的点构成一条合法路径。

情况 \(2\) 可以通过记录一个颜色数组,将访问过的到 \(x\) 的路径上没有与之颜色相同的点的节点的颜色进行统计。两棵不同的子树之间的路径匹配时,直接使用颜色数组即可。

接下来就是点分治模板了。每次取重心,统计贡献,删除,递归点分治子树。即可统计所有合法路径。

实现得比较差,常数较大。

#include <bits/stdc++.h>
using namespace std;
struct edge
{
long long v,nxt;
}e[600000];
long long t,n,a[300000],s[300000],h[300000],del[300000],he=0,cnt=0,ans=1e10,tol=0;
long long pre[300000],x[300000],sum[300000],g[300000];
void init()
{
for(int i=1;i<=n;i++)del[i]=0,h[i]=0;
tol=0,cnt=0;
} void add_edge(long long u,long long v)
{
e[++cnt].nxt=h[u];
e[cnt].v=v;
h[u]=cnt;
} long long dfs1(long long now,long long fa,long long cnt)
{
long long maxn=0;
s[now]=1;
if(del[now])return 0;
for(long long i=h[now];i;i=e[i].nxt)
if(e[i].v!=fa)
{
long long z=dfs1(e[i].v,now,cnt);
s[now]+=z,maxn=max(maxn,z);
}
if(max(maxn,cnt-s[now])<ans)ans=min(ans,max(maxn,cnt-s[now])),he=now;
return s[now];
} void dfs2(long long now,long long fa)
{
if(del[now])return;
s[now]=1,pre[now]=x[a[now]],x[a[now]]=now;
if(pre[now]==0)
{
if(a[now]==a[he])tol++;
else
{
tol+=sum[a[now]];
g[a[now]]++;
}
}
for(long long i=h[now];i;i=e[i].nxt)
if(e[i].v!=fa)
{
dfs2(e[i].v,now);
if(del[e[i].v]==0)s[now]+=s[e[i].v];
}
x[a[now]]=pre[now];
} void update(long long now,long long fa)
{
if(del[now])return;
sum[a[now]]+=g[a[now]],g[a[now]]=0;
for(long long i=h[now];i;i=e[i].nxt)
if(e[i].v!=fa)update(e[i].v,now);
} void clear(long long now,long long fa)
{
if(del[now])return;
pre[now]=0,x[a[now]]=0,sum[a[now]]=0;
for(long long i=h[now];i;i=e[i].nxt)
if(e[i].v!=fa)clear(e[i].v,now);
} void dfz(long long now,long long siz)
{
if(del[now])return;
ans=1e10;
dfs1(now,0,siz);
for(long long i=h[he];i;i=e[i].nxt)
{
dfs2(e[i].v,he);
update(e[i].v,he);
}
for(long long i=h[he];i;i=e[i].nxt)clear(e[i].v,he);
del[he]=1;
for(long long i=h[he];i;i=e[i].nxt)dfz(e[i].v,s[e[i].v]);
} int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
init();
for(long long i=1;i<=n;i++)scanf("%lld",&a[i]);
for(long long i=1;i<=n-1;i++)
{
long long u=0,v=0;
scanf("%lld%lld",&u,&v);
add_edge(u,v),add_edge(v,u);
}
dfz(1,n);
printf("%lld\n",tol);
}
return 0;
}

CF1923E Count Paths 题解的更多相关文章

  1. [CF1188B]Count Pairs 题解

    前言 这道题目是道好题. 第一次div-2进前100,我太弱了. 题解 公式推导 我们观察这个式子. \[(a_i+a_j)(a_i^2+a_j^2)\equiv k \mod p\] 感觉少了点什么 ...

  2. CF293B Distinct Paths题解

    CF293B Distinct Paths 题意 给定一个\(n\times m\)的矩形色板,有kk种不同的颜料,有些格子已经填上了某种颜色,现在需要将其他格子也填上颜色,使得从左上角到右下角的任意 ...

  3. "Shortest" pair of paths[题解]

    "Shortest" pair of paths 题目大意 给出 \(n\) 个点,\(m\) 条边,除第一个点和最后一个点外,其他所有的点都只能被经过一次,要求找到两条从第一个点 ...

  4. POJ3068:"Shortest" pair of paths——题解

    http://poj.org/problem?id=3068 题目大意: 从0-n-1找到两条边和点都不相同(除了0和n-1外)的最小费用路径. ——————————————————————————— ...

  5. POJ3177:Redundant Paths——题解

    http://poj.org/problem?id=3177 明显要求桥的一道题. (因为有桥就说明只能从那一条路走,换句话说就是只有一种方法) 求完桥后按照结论(加几条边成双连通图的结论,不会请ba ...

  6. E. Number of Simple Paths 题解(思维)

    题目链接 题目大意 给你n个点(\(\sum n<=2e5\)),n条边,求有多少条路径 题目思路 要明白任意两点的路径只能是1条或者2条 先topo找环(双向边也是可以找的) 然后把环上的每个 ...

  7. [Leetcode Week12]Unique Paths

    Unique Paths 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/unique-paths/description/ Description A ...

  8. CF981H K Paths

    CF981H K Paths 题解 一道不错的分治ntt题目 题目稍微转化一下,就是所有k条链的存在交,并且交的部分都被覆盖k次 所以一定是两个点,之间路径选择k次,然后端点两开花 f[x]表示x子树 ...

  9. Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics)部分(A~E)题解

    (A) Even Subset Sum Problem 题解:因为n非常非常小,直接暴力枚举所有区间即可. #include<bits/stdc++.h> using namespace ...

  10. CF14D题解

    CF14D Two Paths题解 题目链接 传送门 题意简述 给定一棵树,找出两条不经过相同点的最长路径,使得他们的长度乘积最大. 题目分析 首先,如果在一棵树上,两条路径没有共同的点,那么这两条路 ...

随机推荐

  1. Springboot+MongoDB添加数据时会自带_class字段

    _class字段作用 帮助映射子类,为了方便处理Pojo中存在继承的情况,增加系统的扩展性 去除_class字段 新增mongodb的配置类,配置mappingMongoConverter,配置类网上 ...

  2. wordpress插件开发时如何通过js调用图库/媒体选择器的问题

    效果: 原文地址: wordpress插件开发通过js调用图库/媒体选择器的问题 - 搜栈网 (seekstack.cn)

  3. 小白也能行【手撕ResNet代码篇(附代码)】:详解可复现

    目录 前言 model BasicBlock 和Bottleneck ResNet ResNet18\34\50\101\152 data train test 代码运行以及测试结果 前言 之前已经给 ...

  4. RabbitMq在win10上的安装、用户管理及控制台Demo

    思路: 安装elang--设置elang的环境变量--安装erlang版本对应的rabbitmq--设置rabbitmq的环境变量--安装rabbitmq的可视化管理插件 相关链接: RabbitMQ ...

  5. 鸿蒙开发中console.log和hilog的区别

    在日常开发中打印日志是调试程序非常常用的操作,在鸿蒙的官方文档中介绍了hilog这种方式,有些前端转过来的友友发现console.log也可以进行日志打印.有一段时候幽蓝君也非常喜欢使用console ...

  6. JS 原型链的终点

    从对 js 原型和原型链查找的特性, 我们知道了两个最为重要的结论: 函数对象天生存在 prototype 属性, 它是一个对象, 而它的 constructor 属性指回 函数自身 构造函数的 pr ...

  7. 私有资产测绘&安全流水线Shovel

    私有资产测绘&安全流水线Shovel(Preview)发布 发布版本:Shovel-v0.1.7 当前项目发布版本 Shovel-v0.1.7(预览版) | 企业级资产测绘管理,开启资配漏补新 ...

  8. Seata源码—4.全局事务拦截与开启事务处理

    大纲 1.Seata Server的启动入口的源码 2.Seata Server的网络服务器启动的源码 3.全局事务拦截器的核心变量 4.全局事务拦截器的初始化源码 5.全局事务拦截器的AOP切面拦截 ...

  9. ASP.NET Core已有数据库,却新建项目

    ASP.NET Core已有数据库,却新建项目,只需要构造出相应的类,DbContext,然后直接add-migration init即可!!而不用执行update-database,执行后者会报错: ...

  10. vue之sync

    在 Vue 中,.sync 是一个用于实现双向数据绑定的特殊修饰符.它允许父组件通过一种简洁的方式向子组件传递一个 prop,并在子组件中修改这个 prop 的值,然后将修改后的值反馈回父组件,实现双 ...