思路:

因为有深度的限制,并且我们是在线段树上维护权值,所以我们把点按照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. halcon 模板匹配 -- 转化 vector_angle_to_rigid

    ********************************模板匹配 ********************create_shape_model创建模板,这个函数有许多参数,其中金字塔的级数由N ...

  2. hadoop单机环境配置

    1.配置一台linux服务器(当前使用CentOS7)及一些基本设置 1.1在wmware下制作一台centos服务器(桥接模式)         并设置静态ip (编辑/etc/sysmconfig ...

  3. C#遍历/反射 属性/字段

    public static string SortParam<T>(T t) { string tStr = string.Empty; if (t == null) { return s ...

  4. apicloud常用分享方法

    app中经常会有分享的功能,不管是分享商品还是文字还是图片或者是发送给微信好友扣扣好友,一下做一总结. 分享的样式(分享所有的样式模块):MNActionButton. 在apicloud 中添加这个 ...

  5. jquery相关常用的工具函数

    1.弹出提示框: function prompt(msg){ $("<div>" + msg + "</div>").css({ &qu ...

  6. Java---23种设计模式(九)------组合模式

    一.什么是组合模式 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象. 组合模式依据树形结构来组合对象,用来表示部分以及整体层次. 这种类型的 ...

  7. AD 域服务简介(一)- 基于 LDAP 的 AD 域服务器搭建及其使用(转)

    一.前言 1.1 AD 域服务 什么是目录(directory)呢? 日常生活中使用的电话薄内记录着亲朋好友的姓名.电话与地址等数据,它就是 telephone directory(电话目录):计算机 ...

  8. PAT_A1108#Finding Average

    Source: PAT A 1108 Finding Average (20 分) Description: The basic task is simple: given N real number ...

  9. Python画三维图-----插值平滑数据

    一.二维的插值方法: 原始数据(x,y) 先对横坐标x进行扩充数据量,采用linspace.[如下面例子,由7个值扩充到300个] 采用scipy.interpolate中的spline来对纵坐标数据 ...

  10. 1 java开发工具IDEA的使用

    IntelliJ IDEA 2017.1汉化破解版安装图文教程(附汉化补丁) 注册码:http://idea.lanyus.com/  点击在线生成 IntelliJ IDEA 2017.1正式版发布 ...