P5311 [Ynoi2011] 成都七中

题意

给你一棵 \(n\) 个节点的树,每个节点有一种颜色,有 \(m\) 次查询操作。

查询操作给定参数 \(l\ r\ x\),需输出:

将树中编号在 \([l,r]\) 内的所有节点保留,\(x\) 所在连通块中颜色种类数。

每次查询操作独立。

思路

考虑点分树的思想。假设我们已经建出点分树,对于每一个分治中心,我们应该维护什么东西?

我们从分治中心开始遍历,记录遍历到每个点路径上编号的最小值和最大值。很显然,如果遍历到一个询问的 \(x\) 的时候路径上最值范围在询问区间以内,那么对于这个询问 \(x\) 点与分治中心是联通的。

考虑这个分治中心是怎么给询问更新答案的。我们在遍历的时候记录一下到达每个点时的路径最值和该点的颜色,最后统计答案的时候枚举每个满足上述条件的询问的右端点,用"HH的项链"一题的方法用树状数组记录每种颜色的最小编号的最大值的颜色个数,查询区间答案即可。显然,这个时候树状数组里的每一个答案都与分治中心联通,而分治中心又与询问点联通,故能将范围内的答案统计完全。

那么问题来了,每个询问答案被统计几次、在哪里被统计能统计完全呢?

考虑点分树的结构。对于一个询问的编号区间,假设 \(u\) 为询问点 \(x\) 的点分树祖先,\(v\) 为 \(u\) 点分树祖先,且两者都与 \(x\) 联通,那么 \(v\) 包含的范围一定比 \(u\) 大而且完全包含 \(u\) 的范围。我们刚才说在分治中心的统计能将整个范围内的答案都统计完全,所以 \(x\) 在 \(v\) 处被统计一定包含在 \(u\) 处统计的所有答案。

我们再考虑一个事情,若 \(u\ v\) 定义同上,但\(u\) 与 \(x\) 联通而 \(v\) 不与 \(x\) 联通,那么与 \(u\) 相对的 \(v\) 的彼处的所有点都一定不与 \(x\) 联通,因为这些点一定会经过 \(v\) 点。

综上,对于每个点,我们只需要选择一个深度最小的联通的祖先统计答案即可。这时统计的答案是完全的。

然后我们发现我们甚至不需要建出点分树。直接点分治,在每个分治中心搜索出范围内合法的询问,直接按照上述统计方式将询问答案求出,以后都不再更新该询问答案即可。

时间复杂度 \(O(n\log^2n)\),空间复杂度 \(O(n)\)。空间小、时间常数小、代码短的方法谁不喜欢呢~

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=x*10+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=1e5+10;
int n,m,c[maxn],C[maxn],ans[maxn],siz[maxn],rt,mx[maxn],lst[maxn];
bool vis[maxn],mark[maxn];
struct que{
int l,r,id;
que(){}
que(int l,int r,int id):l(l),r(r),id(id){}
bool operator < (const que &b) const {return r<b.r;}
};
vector<int> V[maxn];
vector<que> qu[maxn],a,q;
inline void insert(int x,int k){if(x)for(;x<=n;x+=x&-x) C[x]+=k;}
inline int query(int x){int ans=0;for(;x;x-=x&-x) ans+=C[x]; return ans;}
void getrt(int x,int fa,int S){
siz[x]=1,mx[x]=0;
for(auto u:V[x]) if(!vis[u] and u!=fa) getrt(u,x,S),mx[x]=max(mx[x],siz[u]),siz[x]+=siz[u];
if((mx[x]=max(mx[x],S-siz[x]))<mx[rt]) rt=x;
}
void dfs(int x,int fa,int l,int r){
siz[x]=1,a.emplace_back(l,r,c[x]);
for(auto u:qu[x]) if(!mark[u.id] and u.l<=l and r<=u.r) mark[u.id]=true,q.push_back(u);
for(auto u:V[x]) if(!vis[u] and u!=fa) dfs(u,x,min(l,u),max(r,u)),siz[x]+=siz[u];
}
void solve(int x){
vis[x]=true;
a.clear(),q.clear(),dfs(x,0,x,x);
sort(a.begin(),a.end()),sort(q.begin(),q.end());
for(int i=0,j=0;i<q.size();i++){
while(j<a.size() and a[j].r<=q[i].r){
if(a[j].l>lst[a[j].id]) insert(lst[a[j].id],-1),insert(lst[a[j].id]=a[j].l,1);
++j;
}
ans[q[i].id]=query(n)-query(q[i].l-1);
}
for(auto u:a) insert(lst[u.id],-1),lst[u.id]=0;
for(auto u:V[x]) if(!vis[u]) rt=0,getrt(u,x,siz[u]),solve(rt);
}
inline void work(){
n=read(),m=read(),mx[0]=n+1;
for(int i=1;i<=n;i++) c[i]=read();
for(int u,v,i=1;i<n;i++) u=read(),v=read(),V[u].push_back(v),V[v].push_back(u);
for(int l,r,i=1;i<=m;i++) l=read(),r=read(),qu[read()].emplace_back(l,r,i);
getrt(1,0,n),solve(rt);
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
}
signed main(){
star::work();
return 0;
}

P5311 [Ynoi2011] 成都七中的更多相关文章

  1. 题解 洛谷 P5311 【[Ynoi2011]成都七中】

    每次询问是关于 \(x\) 所在的连通块,所以考虑用点分树来解决本题. 点分树上每个节点所对应的子树,都是原树中的一个连通块.询问中给定 \(x\) 和区间 \([l,r]\),其就已经确定了原树的一 ...

  2. 【BZOJ-4407】于神之怒加强版 莫比乌斯反演 + 线性筛

    4407: 于神之怒加强版 Time Limit: 80 Sec  Memory Limit: 512 MBSubmit: 241  Solved: 119[Submit][Status][Discu ...

  3. C++——类继承

    类库:类库由类声明和实现构成.类组合了数据表示和类方法,因此提供了比函数库更加完整的程序包. 类继承:从已有的类派生出新的类,派生类继承了原有类(称为基类)的特征,包括方法. 通过类继承可以完成的工作 ...

  4. 2015/7/6 (!长期更新!)C语言从零——张呵呵

    随即呈上! By    He_He _S 小组 @成都七中高新OI2015

  5. Python学习笔记【第九篇】:Python面向对象基础

    Python语言中一切皆对象(类.属性.方法.........) 概念 面向对象编程:Object Oriented Programming 简称OOP 面向对象程序设计 面向对象和面向过程都是解决问 ...

  6. HBSX2019 3月训练

    Day 1 3月有31天废话 今天先颓过了就只剩30天了 初步计划 每天一道字符串/数据结构题 图论学习 根据<若干图论模型探讨>(lyd)复习 二分图与网络流学习 <算法竞赛进阶指 ...

  7. BZOJ 4407 于神之怒加强版 (莫比乌斯反演 + 分块)

    4407: 于神之怒加强版 Time Limit: 80 Sec  Memory Limit: 512 MBSubmit: 1067  Solved: 494[Submit][Status][Disc ...

  8. 【比赛游记】THUWC2019酱油记

    往期回顾:THUSC2018酱油记 day 0 早上 7 点的动车,不知道是从哪儿到哪儿的(雾),只知道从福建到广东 233333 一个值得思考的问题:福建人会不会被广东人吃啊? 动车上玩空洞骑士,可 ...

  9. bzoj 4407 于神之怒加强版 (反演+线性筛)

    于神之怒加强版 Time Limit: 80 Sec  Memory Limit: 512 MBSubmit: 1184  Solved: 535[Submit][Status][Discuss] D ...

随机推荐

  1. java基础第一节课随笔

    第一题:1.定义一个HelloWold类2.在类中定义主方法3.在主方法中使用输出语句在dos控制台打印HelloWorld 打印结果如:HelloWorld4.在案例中使用当行注释.多行注释添加相关 ...

  2. java后端知识点梳理——web安全

    跨域 当浏览器执行脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域. 这里的同源指访问的协议.域名.端口都相同. 同源策略是由 Netscape 提出的著名安全策略,是浏览器最核心.基 ...

  3. halcon——缺陷检测常用方法总结(测量拟合)

    引言 机器视觉中缺陷检测分为一下几种: blob分析+特征 模板匹配(定位)+差分:halcon--缺陷检测常用方法总结(模板匹配(定位)+差分) - 唯有自己强大 - 博客园 (cnblogs.co ...

  4. 关于kubernetes的十七个实验(二)

    写在开头 时隔好几天,结束了毕业设计中期答辩,更新第二节. 实验二与Kubeadm Kubeadm解决了以下问题:处理TLS加密配置,部署核心Kubernetes组件并确保其他节点可以轻松加入集群. ...

  5. ClickHouse学习系列之四【副本&分片部署说明】

    背景 以前介绍过ClickHouse相关的系列文章,现在继续说明.本文开始说明ClickHouse的副本与分片,和其他数据库一样,ClickHouse也会出现单节点故障和单节点资源到达上限的情况.所以 ...

  6. Vue指令实现原理

    前言 自定义指令是vue中使用频率仅次于组件,其包含bind.inserted.update.componentUpdated.unbind五个生命周期钩子.本文将对vue指令的工作原理进行相应介绍, ...

  7. R-常见错误

    错误一:选择了未定义的列(Undefined columns are selected) 改正方法:把目标列转换成因子类型(as.factor) 使用代码如下: 或者: 错误二:太多(36119)的重 ...

  8. 你真的懂 export default 吗?

    export default A 和 export { A as default } 乍一看是一样的,但是里面有一些细微的区别比较容易留坑.本文介绍两种写法的不同之处. import 语句导入的是引用 ...

  9. SpringBoot:Sqlite3+SpringBoot2.1.3+Mybatis-Puls整合项目

    应公司要求完成sqlite3数据库的增改查小功能,特此记录一下. 1.建造项目 结构如下 因为是提供给前端调用所以做了接口. 2.Pom依赖文件 下面是这个项目所依赖的jar包. <parent ...

  10. SpringMVC(6)数据验证

    在系列SpringMVC(4)数据绑定-1.SpringMVC(5)数据绑定-2中我们展示了如何绑定数据,绑定完数据之后如何确保我们得到的数据的正确性?这就是我们本篇要说的内容 -> 数据验证. ...