Regions

这里提供一种时间复杂度不那么优秀但十分好写也好理解的做法。

题目大意

给定一颗 \(n\) 个节点的树,每个节点拥有一个颜色,进行若干次询问,每次询问给出两种颜色 \(A,B\),求所有颜色为 \(A\) 的节点的子树中颜色为 \(B\) 的节点的个数的和。

思路分析

考虑根号分治。按颜色的节点数进行分类,节点数 \(>\sqrt n\) 的称为重颜色,节点数 \(\le \sqrt n\) 的称为轻颜色

对询问进行分类讨论:

  • \(A,B\) 均为轻颜色:

考虑到两者的节点数都不会很多,可以暴力标记每一个颜色为 \(B\) 的点,并枚举所有颜色为 \(A\) 的点,求出其子树中的标记数并累加入答案。这一过程可以用树状数组实现。单次实现的时间复杂度为 \(O(\sqrt n\log n)\)。

  • \(A\) 为重颜色,\(B\) 为轻颜色:

设 \(f_{i,j}\) 表示点 \(i\) 到根的路径中颜色为重颜色 \(j\) 的节点的数量,那么答案显然为:

\[\sum\limits_{i\in \text{col}_B}f_{i,A}
\]

其中,\(\text{col}_X\) 表示所有颜色为 \(X\) 的点所构成的集合。

考虑计算 \(f\):

枚举每一个重颜色 \(K\),遍历 \(\text{col}_K\),将其中的每一个点的子树中的所有点的权值加 \(1\),再遍历每一个颜色不为 \(K\) 的点,其权值就是其对应的 \(f\)。这一过程可以用差分实现。时间复杂度为 \(O(n\sqrt n)\)。

  • \(B\) 为重颜色,\(A\) 为轻颜色:

设 \(g_{i,j}\) 表示点 \(i\) 的子树中颜色为重颜色 \(j\) 的节点的数量,那么答案显然为:

\[\sum_{i\in \text{col}_A}g_{i,B}
\]

\(g\) 的计算与 \(f\) 正好相反:

枚举每一个重颜色 \(K\),遍历 \(\text{col}_K\),将其中的每一个点的权值单点加 \(1\)。再遍历每一个颜色不为 \(K\) 的点,其子树中的权值和即为其对应的 \(g\),这一过程可以用前缀和实现。时间复杂度为 \(O(n\sqrt n)\)。

  • \(A,B\) 均为重颜色:

容易发现,这种情况是上述两种情况的交集,上述两种情况的答案计算方式均适用于此情况。

实现细节

在实现中,为了优化空间复杂度,可以省去 \(f\) 和 \(g\) 直接累加答案。具体的说,设 \(\text{ans1}_{i,j}\) 表示所有颜色为 \(i\) 的点的子树中颜色为重颜色 \(j\) 的节点的数量的和,\(\text{ans2}_{i,j}\) 表示所有颜色为 \(i\) 的点到根的路径中颜色为重颜色 \(j\) 的节点的数量的和。(也就是第三,二种情况对应的答案)这样可以将空间复杂度由 \(O(n\sqrt n)\) 优化到 \(O(R\sqrt n)\)。

差分和前缀和可以直接在 dfs 序上进行,不需要放到树上。

总时间复杂度为 \(O(q\sqrt n\log n+n\sqrt n)\),瓶颈在于树状数组,卡常后可以通过。

空间复杂度为 \(O(R\sqrt n+n)\),完全可过。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector> using namespace std;
const int N=200100,M=450,R=25500; int idx=1,n,m,q,B,cnt,in1,in2,cur,ans;
int w[N],to[N],nxt[N],head[N];
int c[N],dfn[N],siz[N],big[N],d[N];
int ans1[M][R],ans2[M][R]; vector<int> col[N]; int read(){//卡常用的快读快写
int x=0;char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
} void write(int x){
int k=x/10;if(k) write(k);
putchar(x-(k<<3)-(k<<1)+'0');
} void add(int u,int v){
idx++;to[idx]=v;nxt[idx]=head[u];head[u]=idx;
} void dfs_1(int s){
dfn[s]=++cnt;siz[s]=1;
for(int i=head[s];i;i=nxt[i])
dfs_1(to[i]),siz[s]+=siz[to[i]];
} struct BIT{
int a[N];
#define lowbit(x) ((x)&(-(x)))
void add(int x,int v){
for(;x<N;x+=lowbit(x)) a[x]+=v;
}
int query(int x){
if(!x) return 0;
int ans=0;
for(;x;x-=lowbit(x)) ans+=a[x];
return ans;
}
}tree; int main(){
n=read();m=read();q=read();
B=sqrt(n);
w[1]=read();
col[w[1]].push_back(1);
for(int i=2;i<=n;i++){
in1=read();w[i]=read();
add(in1,i);
col[w[i]].push_back(i);
}
dfs_1(1);
for(int i=1;i<=m;i++){
if(col[i].size()<=B) continue;
big[i]=++cur;//对每一种重颜色重标号
for(int j=1;j<=n;j++) d[j]=0;
for(auto it:col[i]) d[dfn[it]]++;//单点加
for(int j=1;j<=n;j++) d[j]+=d[j-1];//前缀和
for(int j=1;j<=n;j++){
if(w[j]==i) continue;
ans1[cur][w[j]]+=d[dfn[j]+siz[j]-1]-d[dfn[j]-1];//直接累加答案
}
for(int j=1;j<=n;j++) d[j]=0;
for(auto it:col[i]){
d[dfn[it]]++;//差分
d[dfn[it]+siz[it]]--;//这里其实是 dfn[it]+siz[it]-1+1
}
for(int j=1;j<=n;j++) d[j]+=d[j-1];//对差分序列做前缀和得到原序列
for(int j=1;j<=n;j++){
if(w[j]==i) continue;
ans2[cur][w[j]]+=d[dfn[j]];
}
}
while(q--){
in1=read();in2=read();ans=0;
if(big[in2]){write(ans1[big[in2]][in1]);cout<<'\n'<<flush;continue;}
if(big[in1]){write(ans2[big[in1]][in2]);cout<<'\n'<<flush;continue;}
for(auto it:col[in2]) tree.add(dfn[it],1);//暴力加
for(auto it:col[in1])
ans+=tree.query(dfn[it]+siz[it]-1)-tree.query(dfn[it]-1);
write(ans);cout<<'\n'<<flush;
for(auto it:col[in2]) tree.add(dfn[it],-1);//记得清空
}
return 0;
}

Regions 题解的更多相关文章

  1. [LeetCode]题解(python):130-Surrounded Regions

    题目来源: https://leetcode.com/problems/surrounded-regions/ 题意分析: 给定给一个二维的板,这个板只包括‘X’和‘O’.将被‘X’包围的‘O’变成‘ ...

  2. LeetCode OJ 题解

    博客搬至blog.csgrandeur.com,cnblogs不再更新. 新的题解会更新在新博客:http://blog.csgrandeur.com/2014/01/15/LeetCode-OJ-S ...

  3. 130. Surrounded Regions

    题目: Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is capt ...

  4. 2014年亚洲区域赛北京赛区现场赛A,D,H,I,K题解(hdu5112,5115,5119,5220,5122)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 下午在HDU上打了一下今年北京区域赛的重现,过了5题,看来单挑只能拿拿铜牌,呜呜. ...

  5. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  6. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  7. USACO 6.2 Shaping Regions

    Shaping Regions N opaque rectangles (1 <= N <= 1000) of various colors are placed on a white s ...

  8. Surrounded Regions leetcode java

    题目: Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is capt ...

  9. (第八场)G Counting regions 【欧拉公式】

    题目链接:https://www.nowcoder.com/acm/contest/146/G G.Counting regions | 时间限制:1 秒 | 内存限制:128M Niuniu lik ...

  10. 【leetcode刷题笔记】Surrounded Regions

    Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...

随机推荐

  1. Kubernetes(k8s) Web-UI界面(一):部署和访问仪表板(Dashboard)

    目录 一.系统环境 二.前言 三.仪表板(Dashboard)简介 四.部署Kubernetes仪表板(Dashboard) 五.访问Kubernetes仪表板(Dashboard) 5.1 使用to ...

  2. node使用jsonwebtoken生成token与验证是否过期

    场景 我们可以使用 cookie,session,token 来做鉴权. 下面我们来看一下, 如何使用 token 来做鉴权 jwt.sign 的简单介绍 npm install jsonwebtok ...

  3. 企业级GitLab搭建

    企业级GitLab搭建 一.简介 1.GitLab概述 是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目. Rub ...

  4. MySQL数据库的集群方案

    读写分离结构(主从) 读多写少,也就是对数据库读取数据的压力比较大. 其中一个是主库,负责写入数据,成为写库:其他都是从库,负责读取数据,成为读库. 对我们的要求: 读库和写库的数据一致: 写数据必须 ...

  5. CF1810D Candies题解

    CF1810D Candies 点击查看原题 点击查看思路 经典的小学数学奥数题. 设 \(a\) 为每天往上爬的高度,\(b\) 为每天向下降的高度,\(n\) 为给定的需要爬上去的天数. 请注意, ...

  6. Spring-配置文件(引入其他配置文件,分模块开发)

    引入其他配置文件 实际开发,Spring的配置文件内容非常多,这就导致了Spring配置很复杂且体积很大,所以可以将配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载 & ...

  7. 初识C语言中的typedef、define以及Status

    小阿杰最近开始看数据结构啦嘿嘿嘿, 可惜小阿杰C语言功底稀薄,以此篇随笔记录一下我卑微的学习之路/苦涩/苦涩 首先define没啥好说的,在文件开头,定义一个固定不变的值. #define MAXN ...

  8. 【hack】浅浅说说自己构造hack的一些逻辑~

    怎么说呢,相信很多考过竞赛的同学都会在平时的练习/考试中遭遇过100分但没有AC的情况,结果一看评测结果:subtask的数据点没过! 这时候就是遇到hack数据了,如果被这类数据卡住,说明你的代码可 ...

  9. Topic太多,RocketMQ炸了!

    网上博客常说,kafka的topic数量过多会影响kafka,而RocketMQ不会受到topic数量影响. 但是,果真如此吗? 最近排查一个问题,发现RocketMQ稳定性同样受到topic数量影响 ...

  10. Unity的IUnityLinkerProcessor:深入解析与实用案例

    Unity IUnityLinkerProcessor Unity IUnityLinkerProcessor是Unity引擎中的一个接口,它允许开发者在Unity项目构建时对代码进行链接处理.这个接 ...