【BZOJ4771】七彩树

Description

给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色。请写一个程序,快速回答这些询问。

Input

第一行包含一个正整数T(1<=T<=500),表示测试数据的组数。
每组数据中,第一行包含两个正整数n(1<=n<=100000)和m(1<=m<=100000),表示节点数和询问数。
第二行包含n个正整数,其中第i个数为c[i](1<=c[i]<=n),分别表示每个节点的颜色。
第三行包含n-1个正整数,其中第i个数为f[i+1](1<=f[i]<i),表示节点i+1的父亲节点的编号。
接下来m行,每行两个整数x(1<=x<=n)和d(0<=d<n),依次表示每个询问。
输入数据经过了加密,对于每个询问,如果你读入了x和d,那么真实的x和d分别是x xor last和d xor last,
其中last表示这组数据中上一次询问的答案,如果这是当前数据的第一组询问,那么last=0。
输入数据保证n和m的总和不超过500000。

Output

对于每个询问输出一行一个整数,即答案。

Sample Input

1
5 8
1 3 3 2 2
1 1 3 3
1 0
0 0
3 0
1 3
2 1
2 0
6 2
4 1

Sample Output

1
2
3
1
1
2
1
1

题解:先不考虑深度的限制。我们分别考虑每种颜色。

如果这个颜色只有一个点,那么它对它的所有祖先的贡献都是1,如果有2个点a,b,那么它们对a和b的祖先贡献都是1,其中两者lca的祖先被重复计算了1次,要将它减去。

以此类推,这些点对它们的树链的并的贡献都是1,所以求出树链的并,用线段树维护子树权值和即可。

但是如果考虑深度限制呢?将线段树改成主席树即可,即对于每个深度都维护一棵线段树。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=100010;
int n,m,cnt,tot,ans;
set<int> S[maxn];
set<int>::iterator it;
int to[maxn],next[maxn],head[maxn],fa[19][maxn],dep[maxn],Log[maxn],p[maxn],q[maxn],pd[maxn],Q[maxn],rt[maxn],v[maxn];
struct node
{
int ls,rs,siz;
}s[maxn*50];
void dfs(int x)
{
p[x]=++q[0],Q[q[0]]=x;
for(int i=head[x];i!=-1;i=next[i]) dep[to[i]]=dep[x]+1,dfs(to[i]);
q[x]=q[0];
}
inline int lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
for(int i=Log[dep[a]-dep[b]];i>=0;i--) if(dep[fa[i][a]]>=dep[b]) a=fa[i][a];
if(a==b) return a;
for(int i=Log[dep[a]];i>=0;i--) if(fa[i][a]!=fa[i][b]) a=fa[i][a],b=fa[i][b];
return fa[0][a];
}
bool cmp(int a,int b)
{
return dep[a]<dep[b];
}
void insert(int x,int &y,int l,int r,int a,int b)
{
y=++tot,s[y].ls=s[y].rs=s[y].siz=0;
s[y].siz=s[x].siz+b;
if(l==r) return ;
int mid=(l+r)>>1;
if(a<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,a,b);
else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,a,b);
}
int query(int l,int r,int x,int a,int b)
{
if(!x||(a<=l&&r<=b)) return s[x].siz;
int mid=(l+r)>>1;
if(b<=mid) return query(l,mid,s[x].ls,a,b);
if(a>mid) return query(mid+1,r,s[x].rs,a,b);
return query(l,mid,s[x].ls,a,b)+query(mid+1,r,s[x].rs,a,b);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void work()
{
n=rd(),m=rd(),tot=cnt=ans=q[0]=0;
int i,j,a,b;
memset(head,-1,sizeof(head));
memset(rt,0,sizeof(rt));
memset(fa,0,sizeof(fa));
for(i=1;i<=n;i++) v[i]=rd(),S[i].clear(),pd[i]=i;
for(i=2;i<=n;i++) fa[0][i]=rd(),add(fa[0][i],i),Log[i]=Log[i>>1]+1;
dep[1]=1,dfs(1);
for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) fa[j][i]=fa[j-1][fa[j-1][i]];
sort(pd+1,pd+n+1,cmp);
for(i=1;i<=n;i++)
{
j=pd[i],a=b=0,it=S[v[j]].lower_bound(p[j]);
insert(rt[dep[pd[i-1]]],rt[dep[j]],1,n,p[j],1);
if(it!=S[v[j]].end()) b=Q[(*it)],insert(rt[dep[j]],rt[dep[j]],1,n,p[lca(b,j)],-1);
if(it!=S[v[j]].begin()) it--,a=Q[(*it)],insert(rt[dep[j]],rt[dep[j]],1,n,p[lca(a,j)],-1);
if(a&&b) insert(rt[dep[j]],rt[dep[j]],1,n,p[lca(a,b)],1);
S[v[j]].insert(p[j]);
}
for(i=1;i<=m;i++)
{
a=rd()^ans,b=rd()^ans;
ans=query(1,n,rt[min(dep[a]+b,dep[pd[n]])],p[a],q[a]);
printf("%d\n",ans);
//ans=0;
}
}
int main()
{
int T=rd();
while(T--) work();
return 0;
}//1 4 4 4 2 3 2 1 2 1 3 2 2 2 4 1 4 1

【BZOJ4771】七彩树 主席树+树链的并的更多相关文章

  1. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  2. VIJOS1107 求树的最长链

    vijos1107环游大同80天 学习了一下求树的最长链的方法 最简单的思路就是两次dfs 两次dfs分别有什么用呢? 第一次dfs,求出某个任意的点能到达的最远的点 第二次dfs,从所搜到的最远的点 ...

  3. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  4. BZOJ_3589_动态树_容斥原理+树链剖分

    BZOJ_3589_动态树_容斥原理+树链剖分 题意: 维护一棵树,支持1.子树内点权加上一个数  2.给出k条链,求路径上的点权和(重复的计算一次) (k<=5) 分析: 可以用树剖+线段树解 ...

  5. 树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花

    求树直径的方法在此转载一下大佬们的分析: 可以随便选择一个点开始进行bfs或者dfs,从而找到离该点最远的那个点(可以证明,离树上任意一点最远的点一定是树的某条直径的两端点之一:树的直径:树上的最长简 ...

  6. [BZOJ4539][HNOI2016]树(主席树)

    4539: [Hnoi2016]树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 746  Solved: 292[Submit][Status][D ...

  7. 小结:线段树 & 主席树 & 树状数组

    概要: 就是用来维护区间信息,然后各种秀智商游戏. 技巧及注意: 一定要注意标记的下放的顺序及影响!考虑是否有叠加或相互影响的可能! 和平衡树相同,在操作每一个节点时,必须保证祖先的tag已经完全下放 ...

  8. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  9. 2016湖南省赛 I Tree Intersection(线段树合并,树链剖分)

    2016湖南省赛 I Tree Intersection(线段树合并,树链剖分) 传送门:https://ac.nowcoder.com/acm/contest/1112/I 题意: 给你一个n个结点 ...

  10. 权值线段树&&可持久化线段树&&主席树

    权值线段树 顾名思义,就是以权值为下标建立的线段树. 现在让我们来考虑考虑上面那句话的产生的三个小问题: 1. 如果说权值作为下标了,那这颗线段树里存什么呢? ----- 这颗线段树中, 记录每个值出 ...

随机推荐

  1. TestNG+ReportNG+Maven优化测试报告

    转载:https://www.cnblogs.com/hardy-test/p/5354733.html 首先在eclipse里面创建一个maven项目,具体要配置maven环境,请自行百度搭配环境. ...

  2. vue - config

    build/build.js -> config 详细的config配置走向.

  3. java集合框架小结

    总结例如以下: 1.假设要求线程安全的, 使用Vector.Hashtable 2.假设不要求线程安全,应该使用ArrayList.LinkedList.HashMap 3.假设要求有映射关系,键值对 ...

  4. 火车票订票API 用PHP完成火车票订票流程

    本教程用来演示聚合数据-火车票订票接口的使用流程. 配置好PHP环境,PHP版本最好大于5.5 去聚合数据-火车票订票接口申请key:http://www.juhe.cn/docs/api/id/17 ...

  5. javascript入门系列演示·三种弹出对话框的用法实例

    对话框有三种 1:只是提醒,不能对脚本产生任何改变: 2:一般用于确认,返回 true 或者 false ,所以可以轻松用于 if...else...判断 3: 一个带输入的对话框,可以返回用户填入的 ...

  6. JsonConvert.SerializeObject() 输出josn格式 也就是序列化。

    JsonConvert.SerializeObject() 输出josn格式  也就是序列化. JSON.parse 反序列化  http://www.cnblogs.com/ahlx/p/52280 ...

  7. BASE64Decoder的引用

    project---->properties--->Libraries--->JRE System Library--->Access rules--->Edit---& ...

  8. 云解析DNS使用教程

    云解析(Domain. Name System,简称DNS)是一种高可用性.高可扩展的权威DNS服务和DNS管理服务.它的目的是为企业和开发者提供稳定.安全.智能的把网站域名或应用资源转换为计算机用于 ...

  9. 架构师-盛大许式伟VS金山张宴

    许式伟:作为系统架构师,您一般会从哪些方面来保证网站的高可用性(降低故障时间)? 张宴:很多因素都会导致网站发生故障,从而影响网站的高可用性,比如服务器硬件故障.软件系统故障.IDC机房故障.程序上线 ...

  10. poj 2601 Simple calculations

    Simple calculations Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6559   Accepted: 32 ...