题解 洛谷 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号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...
随机推荐
- 向强大的SVG迈进
作者:凹凸曼 - 暖暖 SVG 即 Scalable Vector Graphics 可缩放矢量图形,使用XML格式定义图形. 一.SVG印象 SVG 的应用十分广泛,得益于 SVG 强大的各种特性. ...
- 07.Easymock的实际应用
第一步下载对应的java包添加到工程中 并静态导入所需要的j类 import static org.easymock.EasyMock.*; 这里有的注意点 package com.fjnu.serv ...
- python0.1
python基础 python是一种高级编程语言,而编程语言分为3种 编程语言 编程语言是一种人与计算机沟通的工具. 编程就是就将人的需求通过攥写编程语言命令计算机完成指令. 编程的意义在于将人类的生 ...
- 线性dp 打鼹鼠
鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的.根据这个特点阿Q编写了一个打鼹鼠的游戏:在一个n*n 的网格中,在某些时刻鼹鼠会在某一个网格探出头来透透气.你可以控 ...
- 并发05--JAVA并发容器、框架、原子操作类
一.ConcurrentHashMap的实现原理与使用 1.为什么要使用ConsurrentHashMap 两个原因,hashMap线程不安全(多线程并发put时,可能造成Entry链表变成环形数据结 ...
- 传统声学模型之HMM和GMM
声学模型是指给定声学符号(音素)的情况下对音频特征建立的模型. 数学表达 用 \(X\) 表示音频特征向量 (观察向量),用 \(S\) 表示音素 (隐藏/内部状态),声学模型表示为 \(P(X|S) ...
- 小师妹学JVM之:逃逸分析和TLAB
目录 简介 逃逸分析和栈上分配 TLAB简介 TLAB详解 设置TLAB空间的大小 TLAB中大对象的分配 TLAB空间中的浪费 总结 简介 逃逸分析我们在JDK14中JVM的性能优化一文中已经讲过了 ...
- 【Oracle】rman中SBT_TYPE类型的备份如何删除
技阳的rman数据库出现删除rman备份失败,原因是出现SBT_TYPE的磁带备份. [BEGIN] 2018/8/13 13:48:42 RMAN> list backup; List of ...
- 最快安装AndroidStudio的方法(小歪整理)
最快安装AndroidStudio的方法(小歪整理)-干货,加速加载和解决无法预览布局文件的等问题 最快安装AndroidStudio的方法(小歪整理) 1.使用解压压缩包的方式安装:android- ...
- Spark 环境问题记录和解决方法
Spark 版本配套表 名称 版本 说明 Spark spark-2.3.0-bin-hadoop2.7 Spark mongo-java-driver-3.5.0.jar 3.5 Mongo驱动 m ...