思路:

因为有深度的限制,并且我们是在线段树上维护权值,所以我们把点按照dep排序,然后一个一个修改...主席树的下标就是dfs序,子树的查询就是区间查询...

但是发现这样怎么去维护LCA呢...因为要求有序,所以我们可以用set来维护相同颜色的节点...如果把一个点加入集合之后这个点前驱为x,后继为y,那么我们去修正,把xy的LCA+1,然后x和当前点的LCA-1,当前点和y的LCA-1...

from neighthorn

//By SiriusRen
#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=;
int n,m,cases,v[N],next[N],first[N],tot,fa[N][],dfn[N],cnt,root[N],lst[N],dep[N];
int tree[N*],lson[N*],rson[N*],xx,yy,ans;
struct Node{int x,deep,col;}node[N];
bool cmp(Node a,Node b){return a.deep<b.deep;}
bool cmp2(Node a,Node b){return a.x<b.x;}
struct Cmp{bool operator()(Node a,Node b){return dfn[a.x]<dfn[b.x];}};
set<Node,Cmp>s[N];set<Node,Cmp>::iterator it,it2,it3;
void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void dfs(int x){
dfn[x]=++cnt;
for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x][])
dep[v[i]]=node[v[i]].deep=node[x].deep+,dfs(v[i]);
lst[x]=cnt;
}
void insert(int l,int r,int &pos,int last,int num,int wei){
pos=++cnt,tree[pos]=tree[last]+wei;
if(l==r)return;
int mid=(l+r)>>;
if(mid<num)lson[pos]=lson[last],insert(mid+,r,rson[pos],rson[last],num,wei);
else rson[pos]=rson[last],insert(l,mid,lson[pos],lson[last],num,wei);
}
int query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return tree[pos];
int mid=(l+r)>>;
if(mid<L)return query(mid+,r,rson[pos],L,R);
else if(mid>=R)return query(l,mid,lson[pos],L,R);
else return query(l,mid,lson[pos],L,R)+query(mid+,r,rson[pos],L,R);
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=;~i;i--)if(dep[x]-(<<i)>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=;~i;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][];
}
int main(){
scanf("%d",&cases);
while(cases--){
memset(first,-,sizeof(first)),ans=tot=cnt=;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&node[i].col),node[i].x=i;
for(int i=;i<=n;i++)scanf("%d",&fa[i][]),add(fa[i][],i);
for(int j=;j<=;j++)for(int i=;i<=n;i++)fa[i][j]=fa[fa[i][j-]][j-];
dep[]=node[].deep=,dfs(),cnt=,sort(node+,node++n,cmp);
for(int i=;i<=n;i++){
int lst=node[i-].deep,now=node[i].deep;
insert(,n,root[now],root[lst],dfn[node[i].x],);
s[node[i].col].insert(node[i]),it=s[node[i].col].find(node[i]);it2=it,++it2;
if(s[node[i].col].size()>&&it!=s[node[i].col].begin()&&it2!=s[node[i].col].end())
it2=it,it2--,it3=it,it3++,insert(,n,root[now],root[now],dfn[lca((*it2).x,(*it3).x)],);
if(it!=s[node[i].col].begin())it2=it,it2--,insert(,n,root[now],root[now],dfn[lca((*it2).x,(*it).x)],-);
it2=it,++it2;
if(it2!=s[node[i].col].end())insert(,n,root[now],root[now],dfn[lca((*it2).x,(*it).x)],-);
}
while(m--){
scanf("%d%d",&xx,&yy),xx^=ans,yy^=ans;
printf("%d\n",ans=query(,n,root[min(dep[xx]+yy,node[n].deep)],dfn[xx],lst[xx]));
}
for(int i=;i<=n;i++)s[i].clear(),root[i]=;
}
}

BZOJ 4771 主席树+倍增+set的更多相关文章

  1. BZOJ_3545_[ONTAK2010]Peaks_主席树+倍增+kruscal重构树+dfs序

    BZOJ_3545_[ONTAK2010]Peaks_主席树+倍增+kruscal重构树 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道 ...

  2. 洛谷P3248 树 [HNOI2016] 主席树+倍增+分治

    正解:主席树+倍增+分治 解题报告: 传送门! 首先看到这题会想到之前考过的这题 但是那题其实简单一些,,,因为那题只要用个分治+预处理就好,只是有点儿思维难度而已 这题就不一样,因为它说了是按照原树 ...

  3. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

  4. bzoj 4539 [Hnoi2016]树——主席树+倍增

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4539 明明就是把每次复制的一个子树当作一个点,这样能连出一个树的结构,自己竟然都没想到.思维 ...

  5. bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】

    算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分 #include<iostream> #include<cstdio> ...

  6. BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)

    Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...

  7. BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增

    建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...

  8. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  9. bzoj 1901 主席树+树状数组

    修改+查询第k小值 单纯主席树修改会打乱所有,所以再套一个树状数组维护前缀和使得修改,查询都是log 对了,bzoj上不需要读入组数,蜜汁re.. #include<cstdio> #in ...

随机推荐

  1. 学习廖雪峰的Python教程之数据类型

    数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...

  2. std::string格式化输入输出

    在C语言中: C函数有sprintf函数, 比较方便, 但是需要知道所需要的内存空间是多少. 在C++的框架MFC中: 在MFC中CString 有Format函数来格式化字符串. 很方便. 难过的是 ...

  3. react基础篇六

    创建 Refs 使用 React.createRef() 创建 refs,通过 ref 属性来获得 React 元素.当构造组件时,refs 通常被赋值给实例的一个属性,这样你可以在组件中任意一处使用 ...

  4. Android进度条控件ProgressBar使用

    ProgressBar有四种样式,圆形的(大,中,小)和直条形的(水平) 对应的style为 <LinearLayout xmlns:android="http://schemas.a ...

  5. Appium Desired Capabilities信息配置

    编写APPium脚本,必须要配置Desired Capabilities信息 Desired Capabilities 在启动 session 的时候是必须提供的. Desired Capabilit ...

  6. JavaEE的起步

    因为某些原因,现在要从.net开发转向J2EE了,在这里记录一下学习经历

  7. lucene7.1.0实现搜索文件内容

    Lucene的使用主要体现在两个步骤: 1 创建索引,通过IndexWriter对不同的文件进行索引的创建,并将其保存在索引相关文件存储的位置中. 2 通过索引查寻关键字相关文档. 首先,我们需要定义 ...

  8. Node.js+Protractor+vscode搭建测试环境(1)

    1.protractor简介 官网地址:http://www.protractortest.org/ Protractor是一个end-to-end的测试框架,从网络上得到的答案是Protractor ...

  9. 在win7下,easyphp安装过程中MSVCR110.DLL没有被指定在WINDOWS上运行,或者它包含错误

    这是安装easyphp后启动时出现的错误界面.查网上一大堆说法,基本上p用没有.真正解决的办法去m$站点 http://www.microsoft.com/zh-CN/download/details ...

  10. 【Codeforces Round #519 by Botan Investments E】Train Hard, Win Easy

    [链接] 我是链接,点我呀:) [题意] [题解] 设每个人做第一题.第二题的分数分别为x,y 我们先假设没有仇视关系. 即每两个人都能进行一次训练. 那么 对于第i个人. 考虑第j个人对它的贡献 如 ...