BZOJ 4771 主席树+倍增+set
思路:
因为有深度的限制,并且我们是在线段树上维护权值,所以我们把点按照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的更多相关文章
- BZOJ_3545_[ONTAK2010]Peaks_主席树+倍增+kruscal重构树+dfs序
BZOJ_3545_[ONTAK2010]Peaks_主席树+倍增+kruscal重构树 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道 ...
- 洛谷P3248 树 [HNOI2016] 主席树+倍增+分治
正解:主席树+倍增+分治 解题报告: 传送门! 首先看到这题会想到之前考过的这题 但是那题其实简单一些,,,因为那题只要用个分治+预处理就好,只是有点儿思维难度而已 这题就不一样,因为它说了是按照原树 ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- bzoj 4539 [Hnoi2016]树——主席树+倍增
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4539 明明就是把每次复制的一个子树当作一个点,这样能连出一个树的结构,自己竟然都没想到.思维 ...
- bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】
算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分 #include<iostream> #include<cstdio> ...
- BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)
Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增
建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- bzoj 1901 主席树+树状数组
修改+查询第k小值 单纯主席树修改会打乱所有,所以再套一个树状数组维护前缀和使得修改,查询都是log 对了,bzoj上不需要读入组数,蜜汁re.. #include<cstdio> #in ...
随机推荐
- ROS:使用ubuntuKylin17.04安装ROS赤xi龟
使用ubuntuKylin17.04安装 参考了此篇文章:SLAM: Ubuntu16.04安装ROS-kinetic 重复官方链接的步骤也没有成功. 此后发现4.10的内核,不能使用Kinetic. ...
- SLAM:使用G2O-ORB-SLAM(编译)
前言: 没有新雪,看看自己所做的事情,有没有前人做过.果然,EKF_SLAM的版本出现了Android版本的OpenEKFMonoSLAM, G2O-ORB SLAM也出现了VS2012版本. 一.S ...
- OpenCV:使用 随机森林与GBDT
随机森林顾名思义,是用随机的方式建立一个森林.简单来说,随机森林就是由多棵CART(Classification And Regression Tree)构成的.对于每棵树,它们使用的训练集是从总的训 ...
- 初识cocos creator的一些问题
本文的cocos creator版本为v1.9.01.color赋值cc.Label组件并没有颜色相关的属性,但是Node有color的属性. //如果4个参数,在ios下有问题let rgb = [ ...
- json简介及josn数组中取字符
1.json字符串就是字符串,只不过格式是Json格式的,以键值对的形式存在,键和值可以是字符串,数字,空值,数组等. json对象在花括号中书写,一个json对象包含多个键值对,json对象以花括号 ...
- Day 17 time,datetime,random,os,sys,json,pickle
time模块 1.作用:打印时间,需要时间的地方,暂停程序的功能 时间戳形式 time.time() # 1560129555.4663873(python中从1970年开始计算过去了多少秒) 格式化 ...
- eas之新建窗口
public void actionObjectProp_actionPerformed(ActionEvent e) throws Exception { UIContex ...
- POJ 3126 Prime Path (BFS + 素数筛)
链接 : Here! 思路 : 素数表 + BFS, 对于每个数字来说, 有四个替换位置, 每个替换位置有10种方案(对于最高位只有9种), 因此直接用 BFS 搜索目标状态即可. 搜索的空间也不大. ...
- tesuto-Mobius
求 \begin{equation*}\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=k]\end{equation*} 的值. 莫比乌斯反演吧. \begin{align*}& ...
- [USACO5.5]隐藏口令Hidden Password [最小表示法模板]
最小表示法就是一个字符串构成一个环,找以哪个点为开头字典序最小. 然后我们就可以用n2的算法愉快的做啦~实际上有O(n)的做法的,就是用两个指针扫,如果这两个位置的字典序相等,就一起往后,如果某一个大 ...