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. 如何将视频文件.h264和音频文件.mp3复用为输出文件output.mp4?

    一.初始化复用器 在这个部分我们可以分三步进行:(1)打开输入视频文件上下文句柄 (2)打开输入音频文件上下文句柄 (3)打开输出文件上下文句柄 1.打开输入视频文件上下文句柄 在这一步,我们主要用到 ...

  2. 完全兼容DynamoDB协议!GaussDB(for Cassandra)为NoSQL注入新活力

    摘要:DynamoDB是一款托管式的NoSQL数据库服务,支持多种数据模型,广泛应用于电商.社交媒体.游戏.IoT等场景. 本文分享自华为云社区<完全兼容DynamoDB协议!GaussDB(f ...

  3. Kubernetes(k8s) 资源限制:resources,LimitRange,ResourceQuota

    目录 一.系统环境 二.前言 三.Kubernetes资源限制简介 四.创建没有资源限制的pod 4.1 创建没有资源限制的pod 4.2 内存消耗测试 五.使用resources字段配置资源限制 5 ...

  4. Unity 4.6 bate 20 or 4.5.5 +vuforia3.0.9 发布到真机错误 解决

    错误图 +错误码 014-11-20 15:45:49.224 youzheng[6527:1035587] ################### enable 32014-11-20 15:45: ...

  5. JAVA代码下载TXT文件(本地和服务器上的代码都可以)

    // 读取服务器文件内容(TXT文件测试可以) public static List<String> showTxt(String filePath) throws IOException ...

  6. 3D降噪_时域降噪待补充

    视频去噪方法按照处理域的不同可分为空间域.频域.小波域.时域.时-空域去噪等,但是不同域之间的去噪方法会发生重叠现象,或者一种去噪方法会或涉及多个处理域.例如,在时域或时-空域去噪方法中也可使用频域的 ...

  7. subprocess Python执行系统命令最优选模块

    简介 subprocess 是 Python 中执行操作系统级别的命令的模块,所谓系级级别的命令就是如ls /etc/user ifconfig 等和操作系统有关的命令. subprocess 创建子 ...

  8. Linux 命令:rpm查询选项

    rpm(8) System Manager's Manual rpm(8) 名称 rpm - RPM 软件包管理器 查询选项 rpm的查询命令通常的格式如下: rpm -q [query-option ...

  9. win10安装mysql-8.0.19-winx64

    第一步:去官网下载安装 (重点)第二步:先解压,然后在mysql下创建一个my.ini文件,更改my.ini文件里面的两行安装目录,第二行加上\data,my.ini文件不能多或少一个符号,内容见文章 ...

  10. tcpdump抓指定端口/ip的数据包

    抓指定端口,这里以7070端口为例 tcpdump -i ens192 port 7070 -s 0 -l -A -w /chris/70.pcap ens192是网卡  抓完ctrl c停止 抓指定 ...