[BZOJ4771]七彩树(主席树)
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]七彩树(主席树)的更多相关文章
- 线段树简单入门 (含普通线段树, zkw线段树, 主席树)
线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...
- 【BZOJ4771】七彩树 主席树+树链的并
[BZOJ4771]七彩树 Description 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j], ...
- 【BZOJ3439】Kpm的MC密码 trie树+主席树
Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- HDU5790 Prefix 字典树+主席树
分析:这个题和spoj的d_query是一个题,那个是求一段区间里有多少个不同的数字,这里是统计有多少个不同的前缀 用字典树进行判重,(和查询不同的数字一样)对于每个不同的前缀,只保留它最后一次出现的 ...
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 635 Solved: 177[Submit][Stat ...
- BZOJ 4539: [Hnoi2016]树 [主席树 lca]
4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- UOJ#218. 【UNR #1】火车管理 线段树 主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和 ...
随机推荐
- php的几个面试题
1. mysql_num_fields() 返回结果集中字段的数目 如: $result = mysql_query("SELECT id,name,age FROM mydb.tb1 wh ...
- 《区块链100问》第78集:EOS是什么?
EOS是一个区块链开发平台,具有可扩展性强.支持大规模商业应用等特点. 首先,EOS采取DPoS共识算法及其他技术手段预期实现每秒百万级别交易请求,将能够支持数千个商业级的DAPPs. 以太坊是一条公 ...
- std::max 错误
Today I typed the following: int t = (std::max)(timeout, lagtime); Why did I put parentheses around ...
- Sysmon + NXlog构建简单的windows安全监控
工具: Sysmon (sysmon 5.0) ,NXlog(nxlog-ce-2.9.1716.msi) . Sysmon监控系统并生成windows event log, NXlog将wind ...
- 列表选择Spinner
1.只用XML配置来显示列表 在res\values中添加一个arrays.xml 1 <?xml version="1.0" encoding="utf-8&qu ...
- WebApi参数问题方案
原文:http://www.cnblogs.com/landeanfen/p/5337072.html
- No.16 selenium学习之路之异常处理
一.常见的几种异常: SyntaxError:语法错误 NameError:试图访问的变量名不存在 IndexError:索引错误,使用的索引不存在,超出序列范围 KeyError:使用了不存在的关键 ...
- java 多线程总结篇3之——生命周期和线程同步
一.生命周期 线程的生命周期全在一张图中,理解此图是基本: 线程状态图 一.新建和就绪状态 当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Jav ...
- Centos之其他帮助命令
选项帮助 命令 -help 获取命令选项的帮助 例如 ls --help 我们会发现用这种方式查看帮助命令 居然还有中文解释: 详细命令帮助info info 命令 -回车:进入子帮助页面(带有*号标 ...
- Effective STL 学习笔记: Thread Safety and STL Container
Table of Contents 1. STL, Thread and SGI 2. STL and Lock 2.1. RAII 2.2. Use Lock in STL 1 STL, Threa ...