题解 洛谷 P5311 【[Ynoi2011]成都七中】
每次询问是关于 \(x\) 所在的连通块,所以考虑用点分树来解决本题。
点分树上每个节点所对应的子树,都是原树中的一个连通块。询问中给定 \(x\) 和区间 \([l,r]\),其就已经确定了原树的一个连通块,所以可以在点分树上找到最大的一个子树包含该连通块,统计其内部合法点的个数即可。
首先处理出点分树上每个点在原树上到点分树根节点的链上所有节点路径经过节点编号的最小值和最大值。对于每个询问,在 \(x\) 到根节点的链上找到深度最浅的一个点,且原树上 \(x\) 到其路径经过节点编号的最小值和最大值在区间 \([l,r]\) 内,这个节点所对应的子树就包含了该询问所对应的连通块,将询问挂到这个节点上。对于这个询问,\(x\) 和找到的这个节点是连通的,所以只需统计子树内有多少节点是和该节点连通,即其子树内有多少个点在原树上到该节点的路径经过节点编号的最小值和最大值在区间 \([l,r]\) 内。
然后可以遍历点分树上每个点的子树来处理询问,因为点分树所有点的子树和为 \(n\ log\ n\) 级别,所以复杂度正确。
设一个节点到其点分树上子树的根节点的节点编号最小值为 \(L\),最大值为 \(R\),对于询问 \([l,r]\),只有当 \(l \leqslant L,r \geqslant R\),且其颜色是第一次出现,该点才会对这个询问产生贡献。可以先对节点和询问的 \(L\) 进行排序,然后维护每种颜色的 \(R\) 的最小值,让最小值对询问产生贡献,用树状数组维护即可。
\(code:\)
#include<bits/stdc++.h>
#define maxn 200010
#define inf 1000000000
#define lowbit(x) (x&(-x))
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,tot,root;
int v[maxn],mi[maxn],ma[maxn],siz[maxn],ans[maxn],t[maxn];
bool vis[maxn];
struct node
{
int l,r,id,type;
};
bool cmp(const node &a,const node &b)
{
if(a.l==b.l) return a.type<b.type;
return a.l>b.l;
}
vector<node> ve[maxn],p[maxn];
struct edge
{
int to,nxt;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to)
{
e[++edge_cnt]=(edge){to,head[from]};
head[from]=edge_cnt;
}
void dfs_root(int x,int fath)
{
siz[x]=1,ma[x]=0;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]||y==fath) continue;
dfs_root(y,x),siz[x]+=siz[y];
ma[x]=max(ma[x],siz[y]);
}
ma[x]=max(ma[x],tot-siz[x]);
if(ma[x]<ma[root]) root=x;
}
void dfs_find(int x,int fath,int l,int r)
{
p[x].push_back((node){l,r,root,0});
ve[root].push_back((node){l,r,v[x],0});
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]||y==fath) continue;
dfs_find(y,x,min(l,y),max(r,y));
}
}
void solve(int x)
{
int now=tot;
vis[x]=true,dfs_find(x,0,x,x);
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]) continue;
root=0,tot=siz[y];
if(siz[y]>siz[x]) tot=now-siz[x];
dfs_root(y,x),solve(root);
}
}
void update(int x,int v)
{
while(x<=n) t[x]+=v,x+=lowbit(x);
}
int query(int x)
{
int v=0;
while(x) v+=t[x],x-=lowbit(x);
return v;
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;++i) read(v[i]),mi[v[i]]=inf;
for(int i=1;i<n;++i)
{
int x,y;
read(x),read(y);
add(x,y),add(y,x);
}
tot=ma[0]=n,dfs_root(1,0),solve(root);
for(int i=1;i<=m;++i)
{
int l,r,x;
read(l),read(r),read(x);
for(int j=0;j<p[x].size();++j)
{
if(l<=p[x][j].l&&r>=p[x][j].r)
{
ve[p[x][j].id].push_back((node){l,r,i,1});
break;
}
}
}
for(int i=1;i<=n;++i)
{
sort(ve[i].begin(),ve[i].end(),cmp);
for(int j=0;j<ve[i].size();++j)
{
node x=ve[i][j];
if(x.type) ans[x.id]=query(x.r);
else if(x.r<mi[x.id])
update(mi[x.id],-1),update(x.r,1),mi[x.id]=x.r;
}
for(int j=0;j<ve[i].size();++j)
{
node x=ve[i][j];
if(!x.type&&mi[x.id]==x.r)
update(x.r,-1),mi[x.id]=inf;
}
}
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}
题解 洛谷 P5311 【[Ynoi2011]成都七中】的更多相关文章
- P5311 [Ynoi2011] 成都七中
P5311 [Ynoi2011] 成都七中 题意 给你一棵 \(n\) 个节点的树,每个节点有一种颜色,有 \(m\) 次查询操作. 查询操作给定参数 \(l\ r\ x\),需输出: 将树中编号在 ...
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- 题解-洛谷P5217 贫穷
洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...
- 题解 洛谷 P2010 【回文日期】
By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...
随机推荐
- 【论文笔记】Pyramidal Convolution: Rethinking Convolutional Neural Networks for Visual Recognition
地址:https://arxiv.org/pdf/2006.11538.pdf github:https://github.com/iduta/pyconv 目前的卷积神经网络普遍使用3×3的卷积神经 ...
- nmap二层发现
使用nmap进行arp扫描要使用一个参数:-sn,该参数表明屏蔽端口扫描而只进行arp扫描. nmap支持ip段扫描,命令:nmap -sn 192.168.1.0/24 nmap速度比arping快 ...
- java中整数的常量优化机制
java正常两个整数类型相加默认提升为int类型,如接受的类型比int小则会报错,当两个整数常量相加不超范围的情况下是不会报错 byte b = 3 +4: 条件:等号的右边必须全部都是整数常量才可以 ...
- 循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
在前面随笔<循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理>介绍了一个系统最初接触到的前端登录处理的实现,但往往对整个系统来说,一般会有很多业务对 ...
- Javascript 中 数组遍历 forin和forof 的区别
定义一个数组 let array = [1, 2, 3, 4]; for (let a in array){ console.log("遍历a的值 "+a+"”,数组中的 ...
- python之re模块(正则表达式)
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. re 模块使 Python 语言拥有全部的正则表达式功能. 正则表达式中,普通字符匹配本身,非打印字符\n .\t等 ...
- File and Code Templates IN IDEA
File and Code Templates (文件代码模板) 如何自定义设置头文件的注释,其中包括一些作者和文件创建时间和版本的设置 先打开File->Settings(或Alt+Ctrl+ ...
- Mariadb之半同步复制集群配置
首先我们来了解下在mariadb/mysql数据库主从复制集群中什么是同步,什么是异步,什么是半同步:所谓同步就是指主节点发生写操作事件,它不会立刻返回,而是等到从节点接收到主节点发送过来的写操作事件 ...
- Netflix OSS套件一站式学习驿站
Netflix OSS是由Netflix公司主导开发的一套代码框架/库,目的是用于解决大规模集群的分布式系统的一连串问题,如:服务发现.负载均衡.熔断降级.限流.网关等.对于当代的Java开发者来说, ...
- C#学习与个人总结
本学期的C#相对来说,自我学习方法大有收获.但自律性.自我约束能力,我是否达到预期的最好效果,这个很难说出口.本学期在图书馆借了一本MySql.微机原理的书看了看,记了一些笔记.感觉知识有一些相同,有 ...