[bzoj4771] 七彩树
题意
给定一棵n个点,每个点带颜色的有根树。点的编号和颜色编号都在1到n,根的编号为1。m次询问,求x子树中与x距离边数不超过k的点中,颜色的种类数目。每个测试点有多组数据。
分析
不妨设1的父亲为0,0包含了所有颜色。不考虑深度限制,对于单独一种颜色c,易知颜色c对于任意两个色c的点之间的路径上的所有询问有且仅有一个贡献,利用树链的并(DFS序+树上差分)即可解决。
考虑深度约束,可以发现按深度对差分序列进行可持久化,使用线段树就可以了。
#include <bits/stdc++.h>
using namespace std;
const int N=500010;
struct Node {
int ls,rs,val;
} t[N*20];
int tot,root[N];
void insert(int&x,int y,int l,int r,int p,int w) {
t[x=++tot]=t[y];
t[x].val+=w; if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) insert(t[x].ls,t[y].ls,l,mid,p,w);
else insert(t[x].rs,t[y].rs,mid+1,r,p,w);
}
int query(int x,int l,int r,int L,int R) {
if(!x) return 0;
if(L<=l&&r<=R) return t[x].val;
int mid=(l+r)>>1, val=0;
if(L<=mid) val+=query(t[x].ls,l,mid,L,R);
if(mid<R) val+=query(t[x].rs,mid+1,r,L,R);
return val;
}
int n,m,ndp,cnt;
int val[N],siz[N],dfn[N],dep[N],fa[N][20];
vector<int> wuer[N];
queue<int> que;
struct Mogic {
int x;
Mogic(int x=0):x(x){}
bool operator<(const Mogic&d) const {return dfn[x]<dfn[d.x];}
};
set<Mogic> d[N];
int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
int dif=dep[x]-dep[y];
for(int i=19; ~i; --i) if((dif>>i)&1) x=fa[x][i];
if(x==y) return x;
for(int i=19; ~i; --i) if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void dfs(int x,int d) {
dfn[x]=++cnt;
dep[x]=dep[fa[x][0]=d]+(siz[x]=1);
for(int i=1; (1<<i)<=dep[x]; ++i) fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=wuer[x].size()-1; ~i; --i) dfs(wuer[x][i],x),siz[x]+=siz[wuer[x][i]];
}
void bfs() {
que.push(1);
while(que.size()) {
int x=que.front(); que.pop();
if(ndp!=dep[x]) {
root[ndp+1]=root[ndp];
ndp++;
}
insert(root[ndp],root[ndp],1,n,dfn[x],1);
set<Mogic>::iterator k=d[val[x]].insert(Mogic(x)).first;
set<Mogic>::iterator k1=k,k2=k; k1--; k2++;
if(k!=d[val[x]].begin()&&k2!=d[val[x]].end()) insert(root[ndp],root[ndp],1,n,dfn[lca(k1->x,k2->x)],1);
if(k!=d[val[x]].begin()) insert(root[ndp],root[ndp],1,n,dfn[lca(k1->x,x)],-1);
if(k2!=d[val[x]].end()) insert(root[ndp],root[ndp],1,n,dfn[lca(x,k2->x)],-1);
for(int i=wuer[x].size()-1; ~i; --i) que.push(wuer[x][i]);
}
}
int main() {
// freopen("a.in","r",stdin);
int T,last;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&m);
tot=cnt=last=ndp=0;
for(int i=1; i<=n; ++i) {
memset(fa[i],0,sizeof fa[i]);
scanf("%d",&val[i]);
wuer[i].clear();
d[i].clear();
root[i]=0;
}
for(int i=2,x; i<=n; ++i) {
scanf("%d",&x);
wuer[x].push_back(i);
}
dfs(1,0);
bfs();
for(int x,k; m--; ) {
scanf("%d%d",&x,&k); x^=last,k^=last;
printf("%d\n",last=query(root[min(dep[x]+k,ndp)],1,n,dfn[x],dfn[x]+siz[x]-1));
}
}
return 0;
}
[bzoj4771] 七彩树的更多相关文章
- [BZOJ4771]七彩树(主席树)
https://blog.csdn.net/KsCla/article/details/78249148 用类似经典的链上区间颜色计数问题的做法,这个题可以看成是询问DFS在[L[x],R[x]]中, ...
- BZOJ4771 七彩树(dfs序+树上差分+主席树)
考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...
- BZOJ4771七彩树——可持久化线段树+set+树链的并+LCA
给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节 点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义dept ...
- bzoj4771 七彩树 dfs序+主席树+树链的并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4771 题解 一道不错的树链并的基础练习题. 如果不是树,而是一个数组的话,对于给定区间内的不同 ...
- 【BZOJ4771】七彩树(主席树)
[BZOJ4771]七彩树(主席树) 题面 BZOJ 题解 如果没有深度限制,每次只询问子树内的颜色个数,除了树套树\(dfs\)序加前驱或者后继强行二维数点之外,还有这样一种做法: 把所有相同颜色的 ...
- 【BZOJ4771】七彩树 主席树+树链的并
[BZOJ4771]七彩树 Description 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j], ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- 【bzoj4771】七彩树 树链的并+STL-set+DFS序+可持久化线段树
题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ...
- [BZOJ]2017省队十连测推广赛1 T2.七彩树
题目大意:给你一棵n个点的树,每个点有颜色,m次询问,每次询问一个点x的子树内深度不超过depth[x]+d的节点的颜色数量,强制在线.(n,m<=100000,多组数据,保证n,m总和不超过5 ...
随机推荐
- Cookie和Session的原理和异同
Cookie和Session的原理和异同 原理: cookie: 1.创建Cookie 当用户第一次浏览某个使用Cookie的网站时,该网站的服务器就进行如下工作: ①该用户生成一个唯一的识别码(Co ...
- log4j警告:WARN Please initialize the log4j system properly 的解决方法
出现这个问题的原因则是因为没有为log4j建立配置文件导致的.所以解决问题的方法很简单,只要在 src文件目录下建立配置文件即可: 右键点击src -> New -> File 文件 ...
- linux学习--2019-04-22
1.写命令,vi编辑器 1)vi 文件名 2) 按 ‘i’ 进入编辑模式 3)编写完成后,按Esc,然后输入 “:wq” 推出编辑.(“q!”不存盘,强制退出vi) 2.命令补全 “Tab” 3.获取 ...
- 三、自动化测试平台搭建-django-如何用mysql数据库做web项目
从这节开始到后面说的大概内容如下: 这里说的是Django做一个web项目的大概框架,从下篇具体说Django中的模型(查询..),视图(请求,响应,cookie,session..),模板(验证码, ...
- xpath路径定位
preceding-sibling选择同级层所有节点向前查找 //div[@id='id1']/preceding-sibling::div/a 例如:“更多产”超链接的同级向上数第二个元素,即“登陆 ...
- corel
corel CorelDRAW X6 Corel CorelCAD 2017 32位/64位破解版
- 如何给小学生讲清楚ECC椭圆曲线加密
对于RSA这套公私钥加密的思路,我以为我挺明白的,运用的娴熟自如. 当然现在RSA用的不多,而是基于ECC曲线来做签名验签,最大名鼎鼎的莫过于比特币. 可是前两天和别人讲代码,被问了ECC为什么可以用 ...
- 将Redhat,CentOS,Ubuntu虚拟机的IP设为静态IP的方法
一般在主机上创建的虚拟机默认是通过DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)网络协议来动态生成的,这样会导致你安装的虚拟机的IP地址是动态变化 ...
- npm、cnpm、yarn 安装删除异同
背景 一直觉得npm.cnpm.yarn的安装删除基本一样用哪个都行,不过俗话说的好,实践出真知,这里记录一下今天简单测试得到的结果总结. 可能会有错误,希望大家评论指正,十分感谢. 测试电脑系统:M ...
- leetcode-只出现一次的数字合并两个有序数组
题目:合并两个有序数组 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素 ...