#点分治,树状数组#洛谷 5311 [Ynoi2011] 成都七中
题目
给你一棵 \(n\) 个节点的树,每个节点有一种颜色,有 \(m\) 次查询操作。
查询操作给定参数 \(l\) \(r\) \(x\),需输出:
将树中编号在 \([l,r]\) 内的所有节点保留,\(x\) 所在连通块中颜色种类数。
每次查询操作独立。
分析
首先点分治能够通过经过当前重心的连通块表示出所有的连通块,
考虑一个点 \(y\) 处在 \(x\) 的连通块中
当且仅当 \(x\) 到 \(y\) 的路径上的点下标在 \([l,r]\) 范围内。
那么每次分治到一个新的重心,求出每个点到根节点的最小下标 \(L\) 和最大下标 \(R\)。
可以发现这个询问可以在这个重心被计算当且仅当 \(l\leq L\leq R\leq r\),并且只要询问过就不需要递归下去。
那么只要这个条件满足就把它加入待询问的数组中,相当于在该重心的子树中提供 \((L,R,Col)\),询问颜色个数。
那么将询问和这些点均按 \(l\) 从大到小排序,然后对于颜色记录前驱(HH的项链),
尽量使其出现的右端点尽量靠左(取最小值),然后用树状数组维护不超过其右端点的右端点个数。
时间复杂度 \(O((n+Q)\log ^2n)\)
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100011; struct node{int y,next;}e[N<<1]; struct rec{int l,r,z;}E[N],b[N];
int siz[N],big[N],as[N],hs[N],rk[N],n,et=1,Q,ans[N],v[N],root,tot,TOT,a[N],las[N],c[N];
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
void update(int x,int y){
	for (;x<=n;x+=-x&x) c[x]+=y;
}
int query(int x){
	int ans=0;
	for (;x;x-=-x&x) ans+=c[x];
	return ans;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void dfs(int x,int fa){
	siz[x]=1,big[x]=0;
	for (int i=as[x];i;i=e[i].next)
	if (!v[e[i].y]&&e[i].y!=fa){
		dfs(e[i].y,x),siz[x]+=siz[e[i].y];
		big[x]=max(big[x],siz[e[i].y]);
	}
	big[x]=max(big[x],big[0]-siz[x]);
	if (big[x]<=big[root]) root=x;
}
void Dfs(int x,int fa,int l,int r){
	b[++tot]=(rec){l,r,a[x]};
	for (int i=hs[x],now=0;i;i=E[i].z)
	if (E[i].l<=l&&r<=E[i].r){
		rk[++TOT]=i;
		if (!now) hs[x]=E[i].z;
		    else E[now].z=E[i].z;
	}else now=i;
	for (int i=as[x];i;i=e[i].next)
	if (!v[e[i].y]&&e[i].y!=fa)
		Dfs(e[i].y,x,min(l,e[i].y),max(r,e[i].y));
}
bool cmp0(rec x,rec y){return x.l>y.l;}
bool cmp1(int x,int y){return E[x].l>E[y].l;}
void Dp(int x){
	v[x]=1,tot=TOT=0,Dfs(x,0,x,x);
	sort(b+1,b+1+tot,cmp0),sort(rk+1,rk+1+TOT,cmp1);
	int j=1;
	for (int i=1;i<=TOT;++i){
		for (;j<=tot&&b[j].l>=E[rk[i]].l;++j)
		if (las[b[j].z]>b[j].r){
			update(las[b[j].z],-1);
			update(las[b[j].z]=b[j].r,1);
		}
		ans[rk[i]]=query(E[rk[i]].r);
	}
	for (int i=1;i<j;++i)
	if (las[b[i].z]!=0x3f3f3f3f)
		update(las[b[i].z],-1),las[b[i].z]=0x3f3f3f3f;
	for (int i=as[x];i;i=e[i].next) if (!v[e[i].y])
		big[0]=siz[e[i].y],dfs(e[i].y,root=0),Dp(root);
}
int main(){
	n=iut(),Q=iut();
	memset(las,0x3f,sizeof(las));
	for (int i=1;i<=n;++i) a[i]=iut();
	for (int i=1;i<n;++i){
		int x=iut(),y=iut();
		e[++et]=(node){y,as[x]},as[x]=et;
		e[++et]=(node){x,as[y]},as[y]=et;
	}
	for (int i=1;i<=Q;++i){
		int l=iut(),r=iut(),x=iut();
		E[i]=(rec){l,r,hs[x]},hs[x]=i;
	}
	big[0]=n,dfs(1,0),Dp(root);
	for (int i=1;i<=Q;++i) print(ans[i]),putchar(10);
	return 0;
}
												
											#点分治,树状数组#洛谷 5311 [Ynoi2011] 成都七中的更多相关文章
- 树状数组 洛谷P3616 富金森林公园
		
P3616 富金森林公园 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积水也有 ...
 - BZOJ_3262_陌上花开_CDQ分治+树状数组
		
BZOJ_3262_陌上花开_CDQ分治+树状数组 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的 ...
 - 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
		
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
 - BZOJ 1176 Mokia CDQ分治+树状数组
		
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
 - 【bzoj3262】陌上花开  CDQ分治+树状数组
		
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
 - 【bzoj2225】[Spoj 2371]Another Longest Increasing  CDQ分治+树状数组
		
题目描述 给定N个数对(xi, yi),求最长上升子序列的长度.上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj. 样例输入 8 1 3 3 2 1 1 4 5 ...
 - BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组
		
BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组 Description P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n p a , , 之后, ...
 - BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组
		
BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...
 - BZOJ_2225_[Spoj 2371]Another Longest Increasing_CDQ 分治+树状数组
		
BZOJ_2225_[Spoj 2371]Another Longest Increasing_CDQ 分治+树状数组 Description 给定N个数对(xi, yi),求最长上升子 ...
 - BZOJ_2683_简单题&&BZOJ_1176_[Balkan2007]Mokia_CDQ分治+树状数组
		
BZOJ_2683_简单题&&BZOJ_1176_[Balkan2007]Mokia_CDQ分治+树状数组 Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加 ...
 
随机推荐
- Direct2D 另一种与D3D创建类似的方法
			
在进行D2D学习的时候,发现了这样一篇文档, Direct2D Quickstart for Windows 8 只有这么一小段介绍, Direct2D is a native-code, immed ...
 - win32 - 以编程方式访问远程计算机上的文件
			
第一步,在一台计算机上将某个驱动器或者某个文件夹设为sharing模式.这是我们需要访问的共享文件夹.(不需要设置everyone权限) 第二步,我们需要为两台在同一domain下的计算机上建立连接. ...
 - [Rust] 数据类型的转换
			
数据类型的转换 类型转换的方式 Rust 提供了多种类型转换的方式. as T 用于数类型之间的转换.ixx, uxx, fxx 都可以. 注意:当溢出的时候,转换不会 panic,而是循环映射值. ...
 - 【Azure Developer】解答《美丽的数学》一书中P120页的一道谜题:寻找第四个阶乘和数
			
一道谜题 在观看<美丽的数学>一书中,在120页中有一道谜题: 数字145被称为一个阶乘和数, 因为它具有以下有趣的属性,如果我们将它的各位数字的阶乘相加,会得到该数字本身 1! +4! ...
 - 【Azure 存储服务】关于对Azure Storage Account 的 Folder 权限管理和设定
			
问题描述 在一个storage account下面有很多folder,需要对不同的folder设置不同的权限给到不同的用户来访问使用,怎么样设定比较合理? 问题解答 一:可以使用SAS共享访问签名进行 ...
 - FeignClient 报错: A bean with that name has already been defined and overriding is disabled.
			
1. 错误信息 *************************** APPLICATION FAILED TO START *************************** Descript ...
 - 17. Class字节码指令解析
			
## 1. 概述 官方文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html Java 字节码对于虚拟机,就好像汇编语言对于 ...
 - Java synchronized的使用与原理
			
需要明确的几个问题: synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.如果 再细的分类,synchronized可作用于instance变 ...
 - C++中的不规则二维数组
			
技术背景 最近刚学习C++的一些编程技巧,对于一些相对比较陌生的问题,只能采取一些简单粗暴的方案来实现.就比如说,我们可以在Python中定义一个[[0,0,0],[1,2],[1,1,1],[3]] ...
 - javascript web development es6 pdf js - Cheat Sheet 表格 [vuejs / webcomponents-cheatsheet-2021] 共3套
			
ES6 预览 VUE2 预览 webcomponents 预览 ES6 2019 pdf下载: https://files.cnblogs.com/files/pengchenggang/javasc ...