https://blog.csdn.net/KsCla/article/details/78249148

用类似经典的链上区间颜色计数问题的做法,这个题可以看成是询问DFS在[L[x],R[x]]中,深度在[dep[x],dep[x]+d]中,上一个同色点在[0,L[x]-1]中的点的个数。这是个三维数点问题,如果不强制在线的话,可以离线解决一维,主席树解决两维。

强制在线的话,其实还有一个“离线”方法:在所有询问前就将所有答案全部算好。

考虑两个同色点,在不考虑深度的情况下,它们所贡献的点是它们到根的链的并。对于链并问题,往往用set维护dfs序,然后插入点时处理dfs序相邻的两项的信息(差分),可以通过线段树来支持动态差分。

现在考虑深度,按深度建主席树即可。

讲的并不清楚,具体还是看上面的题解吧。代码应该还是比较好理解的。

 #include<set>
#include<cstdio>
#include<vector>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
typedef long long ll;
using namespace std; const int N=,M=;
int T,n,m,u,v,cnt,ans,tim,nd,x,d,co[N],dep[N],h[N],to[N],nxt[N];
int ls[M],rs[M],sm[M],fa[N][],L[N],R[N],pos[N],rt[N];
vector<int>a[N];
set<int>c[N]; void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } void dfs(int x){
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
dep[x]=dep[fa[x][]]+; L[x]=++tim;
pos[tim]=x; a[dep[x]].push_back(x);
For(i,x) dfs(k=to[i]); R[x]=tim;
} int lca(int u,int v){
if (dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v];
for (int i=; ~i; i--) if (t&(<<i)) u=fa[u][i];
if (u==v) return u;
for (int i=; ~i; i--) if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
return fa[u][];
} void ins(int &x,int y,int L,int R,int pos,int k){
x=++nd; ls[x]=ls[y]; rs[x]=rs[y]; sm[x]=sm[y]+k;
if (L==R) return;
int mid=(L+R)>>;
if (pos<=mid) ins(ls[x],ls[y],L,mid,pos,k);
else ins(rs[x],rs[y],mid+,R,pos,k);
} int que(int x,int y,int L,int R,int l,int r){
if (!y) return ;
if (L==l && r==R) return sm[y]-sm[x];
int mid=(L+R)>>;
if (r<=mid) return que(ls[x],ls[y],L,mid,l,r);
else if (l>mid) return que(rs[x],rs[y],mid+,R,l,r);
else return que(ls[x],ls[y],L,mid,l,mid)+que(rs[x],rs[y],mid+,R,mid+,r);
} int main(){
freopen("bzoj4771.in","r",stdin);
freopen("bzoj4771.out","w",stdout);
for (scanf("%d",&T); T--; ){
scanf("%d%d",&n,&m);
rep(i,,n) h[i]=; cnt=tim=ans=nd=;
rep(i,,n) scanf("%d",&co[i]);
rep(i,,n) scanf("%d",&fa[i][]),add(fa[i][],i);
rep(i,,n) a[i].clear(),c[co[i]].clear();
dfs();
rep(i,,n){
rt[i]=rt[i-]; int ed=a[i].size()-;
rep(j,,ed){
int x=a[i][j]; ins(rt[i],rt[i],,n,L[x],); c[co[x]].insert(L[x]);
set<int>::iterator it=c[co[x]].find(L[x]);
int pre=,suf=; it++;
if (it!=c[co[x]].end()) suf=*it; it--;
if (it!=c[co[x]].begin()) it--,pre=*it;
if (pre && suf) ins(rt[i],rt[i],,n,L[lca(pos[pre],pos[suf])],);
if (pre) ins(rt[i],rt[i],,n,L[lca(pos[pre],x)],-);
if (suf) ins(rt[i],rt[i],,n,L[lca(pos[suf],x)],-);
}
}
while (m--){
scanf("%d%d",&x,&d); x^=ans; d^=ans;
printf("%d\n",ans=que(rt[dep[x]-],rt[dep[x]+d],,n,L[x],R[x]));
}
}
return ;
}

[BZOJ4771]七彩树(主席树)的更多相关文章

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

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

  2. 【BZOJ4771】七彩树 主席树+树链的并

    [BZOJ4771]七彩树 Description 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j], ...

  3. 【BZOJ3439】Kpm的MC密码 trie树+主席树

    Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身 ...

  4. 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))

    函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...

  5. HDU5790 Prefix 字典树+主席树

    分析:这个题和spoj的d_query是一个题,那个是求一段区间里有多少个不同的数字,这里是统计有多少个不同的前缀 用字典树进行判重,(和查询不同的数字一样)对于每个不同的前缀,只保留它最后一次出现的 ...

  6. bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Stat ...

  7. BZOJ 4539: [Hnoi2016]树 [主席树 lca]

    4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...

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

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

  9. UOJ#218. 【UNR #1】火车管理 线段树 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和 ...

随机推荐

  1. Linux下ssh的使用

    更多内容推荐微信公众号,欢迎关注: 摘抄自:https://www.cnblogs.com/kevingrace/p/6110842.html 对于linux运维工作者而言,使用ssh远程远程服务器是 ...

  2. ubuntu 14.04安装JDK

    As a workaround, you can install OpenJDK 8 from a PPA repository: 1. Open terminal from the Dash or ...

  3. UNIX环境高级编程 第7章 进程环境

    本章涉及C/C++程序中main函数是如何被调用的.命令行参数如何传递给main函数.程序的内存空间布局.程序如何使用环境变量.程序如何终止退出. main函数 C程序或C++程序总是从main函数开 ...

  4. java7与java8中计算两个日期间隔多少年多少月多少天的实现方式

    最近工作中碰到个新需求,计算每个员工入职公司的时长,要求形式为多少年多少月多少天形式,某个值为0就跳过不显示,因为前段时间学习过java8新特性,对于这个需求,java8的新时间日期API可以直接解决 ...

  5. Redis—数据结构之list

    Redis的列表对象底层所使用的数据结构其中之一就是list. list Redis的list是一个双端链表,其由3部分构成:链表节点.链表迭代器.链表.这一设计思想和STL的list是一样的,STL ...

  6. innobackupex 相关语法讲解【转】

    innobackupex 相关语法讲解 连接服务器 The database user used to connect to the server and its password are speci ...

  7. 2018ICPC南京网络赛

    2018ICPC南京网络赛 A. An Olympian Math Problem 题目描述:求\(\sum_{i=1}^{n} i\times i! \%n\) solution \[(n-1) \ ...

  8. 3->集群架构主机克隆教程

    centos7系统集群主机克隆: 有道笔记链接地址

  9. js中this揭秘

    前端面试题中经常会考this指向问题,初学者通常都会晕头转向,不知所以然.今天我就来讲讲js中this指向问题. this指向大概分为5种情况,记住这6个规律,基本上面试题都能解决. 通过圆括号直接调 ...

  10. Java @SuppressWarnings

    @SuppressWarnings() 注解以@开头可以接受参数 @SuppressWarnings("unchecked") 不受检查的警告信息应该被抑制 //: holding ...