BZOJ 4771: 七彩树 可持久化线段树+树链的并
这个思路挺有意思的 ~
利用树链的并来保证每个颜色只贡献一次,然后用可持久化线段树维护
code:
#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100005
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
using namespace std;
namespace seg
{
#define lson t[x].ls
#define rson t[x].rs
int tot;
struct node
{
int ls,rs,sum;
}t[N*80];
void clr()
{
for(int i=1;i<=tot;++i) t[i].ls=t[i].rs=t[i].sum=0;
tot=0;
}
int newnode()
{
return ++tot;
}
void build(int &x,int l,int r)
{
x=newnode();
if(l==r) return;
int mid=(l+r)>>1;
if(l<=mid) build(lson,l,mid);
if(r>mid) build(rson,mid+1,r);
}
int cop(int x,int l,int r,int p,int v)
{
int now=newnode();
t[now]=t[x];
t[now].sum+=v;
if(l==r) return now;
int mid=(l+r)>>1;
if(p<=mid) t[now].ls=cop(lson,l,mid,p,v);
else t[now].rs=cop(rson,mid+1,r,p,v);
return now;
}
int query(int x,int l,int r,int L,int R)
{
if(!x) return 0;
if(l>=L&&r<=R) return t[x].sum;
int re=0;
int mid=(l+r)>>1;
if(L<=mid) re+=query(lson,l,mid,L,R);
if(R>mid) re+=query(rson,mid+1,r,L,R);
return re;
}
#undef lson
#undef rson
};
set<int>se[N];
set<int>::iterator fr,ba;
int edges,n,m,tim,ct;
int hd[N],to[N],nex[N],col[N],nod[N],st[N],ed[N];
int fa[N],dfn[N],dep[N],size[N],son[N],top[N];
int id[N],rt[N];
bool cmp(int a,int b)
{
return dep[a]<dep[b];
}
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs1(int u,int ff)
{
size[u]=1;
dfn[u]=++tim;
st[u]=dfn[u];
nod[dfn[u]]=u;
dep[u]=dep[ff]+1;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
ed[u]=tim;
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=hd[u];i;i=nex[i])
{
if(to[i]!=son[u])
{
dfs2(to[i],to[i]);
}
}
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void solve()
{
int i,j,last=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i) scanf("%d",&col[i]);
for(i=2;i<=n;++i)
{
scanf("%d",&fa[i]);
add(fa[i],i);
}
dfs1(1,0);
dfs2(1,1);
for(i=1;i<=n;++i) id[i]=i;
sort(id+1,id+1+n,cmp);
int lst=0;
seg::build(rt[0],1,n);
for(i=1;i<=n;++i)
{
int p=id[i];
int c=col[p];
while(dep[p]>lst) rt[lst+1]=rt[lst],++lst;
se[c].insert(dfn[p]);
fr=ba=se[c].lower_bound(dfn[p]),ba++;
if(fr!=se[c].begin())
{
--fr;
rt[lst]=seg::cop(rt[lst],1,n,dfn[LCA(nod[*fr],p)],-1);
++fr;
}
if(ba!=se[c].end())
{
rt[lst]=seg::cop(rt[lst],1,n,dfn[LCA(nod[*ba],p)],-1);
}
if(fr!=se[c].begin()&&ba!=se[c].end())
{
--fr;
rt[lst]=seg::cop(rt[lst],1,n,dfn[LCA(nod[*fr],nod[*ba])],1);
}
rt[lst]=seg::cop(rt[lst],1,n,dfn[p],1);
}
for(i=1;i<=m;++i)
{
int x,d;
scanf("%d%d",&x,&d);
x^=last,d^=last;
last=seg::query(rt[min(n,dep[x]+d)],1,n,st[x],ed[x]);
printf("%d\n",last);
}
for(i=1;i<=n;++i) son[i]=0;
for(i=1;i<=n;++i) hd[i]=0;
for(i=1;i<=edges;++i) nex[i]=to[i]=0;
edges=tim=0;
seg::clr();
for(i=1;i<=n;++i) se[i].clear();
}
int main()
{
// setIO("input");
int i,j,T;
scanf("%d",&T);
while(T--) solve();
return 0;
}
BZOJ 4771: 七彩树 可持久化线段树+树链的并的更多相关文章
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- BZOJ.4771.七彩树(可持久化线段树)
BZOJ 考虑没有深度限制,对整棵子树询问怎么做. 对于同种颜色中DFS序相邻的两个点\(u,v\),在\(dfn[u],dfn[v]\)处分别\(+1\),\(dfn[LCA(u,v)]\)处\(- ...
- bzoj 4771: 七彩树 树链的并+可持久化线段树
题目大意: 给定一颗树,询问树中某个点x的子树中与其距离不超过d的所有点中本质不同的颜色数 强制在线 题解: 一下午终于把这道题叉掉了. 写了三个算法,前两个都是错的,后一个是%的网上大爷们的题解. ...
- BZOJ4771七彩树——可持久化线段树+set+树链的并+LCA
给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节 点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义dept ...
- BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...
- bzoj 2653 二分答案+可持久化线段树
首先离散化,然后我们知道如果对于一个询问的区间[l1,r1],[l2,r2],我们二分到一个答案x,将[l1,r2]区间中的元素大于等于x的设为1,其余的设为-1,那么如果[l1,r1]的最大右区间和 ...
- BZOJ 3439 Kpm的MCpassword Trie树+可持久化线段树
题目大意:给定n个字符串,对于每一个字符串求以这个字符串为后缀的字符串中第k小的编号 首先将字符串反转 那么就变成了对于每一个字符串求以这个字符串为前缀的字符串中第k小的编号 然后考虑对字符串排序 那 ...
- 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665
如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...
随机推荐
- go语言浅析二叉树
Hello,各位小伙伴大家好,我是小栈君,今天给大家带来的分享是关于关于二叉树相关的知识点,并用go语言实现一个二叉树和对二叉树进行遍历. 我们主要针对二叉树的概念,go实战实现二叉树的前序遍历.中序 ...
- [译] QUIC Wire Layout Specification - Introduction & Overview | QUIC协议标准中文翻译(1) 简介和概述
本文同步发布于: https://www.pengrl.com/p/33330/ ,转载请注明出处,谢谢. 目录 Introduction | 简介 Conventions and Definitio ...
- 《JAVA高并发编程详解》-wait和sleep
- .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
原文:.NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用? 都知道可以在任务管理器中查看进程的 CPU 和内存占用,那么如何通过 .NET 编写代码的方式来获取到 ...
- highcharts离线导出图表
到了这里,其实还没有结束,导出图片时,仍会发出两个请求 此时找到offline-exporting.js文件修改其中的libURL 修改为请求自己的网站
- MySQL和SQL Server一些基本用法区别
具体查看:https://www.cnblogs.com/zhaow/articles/9633554.html 转自:https://www.cnblogs.com/zhaow/articles/9 ...
- 《区块链DAPP开发入门、代码实现、场景应用》笔记1——天外飞仙DAPP
Solidity编程语言解决了编写智能合约的不友好的问题,但是当合约编译并部署之后,对与这些接口的访问,对于一般的使用者来说,门槛有点高, 对普通用户来说也是非常不友好,为了使广大用户理解并方便快捷的 ...
- printk打印级别
默认级别 # cat /proc/sys/kernel/printk 4 4 1 7 分别是:控制台日志级别.默认的消息日志级别.最低的控制台日志级别和默认的控制台日志级别 举例 # echo 0 & ...
- 使用虹软ArcFac,java 离线SDK 进行人脸识别
公司项目需要人脸识别登录,需要支持离线识别,所以无法使用在线的人脸识别的API,于是使用到了离线SDK来对比识别人脸相识度. 获取人脸抓拍的图片需要对接设备,这里不做记录,假设我们已经获取到了人脸图片 ...
- 【故障处理】ORA-12162 错误的处理
[故障处理]ORA-12162: TNS:net service name is incorrectly specified 一.1 场景 今天拿到一个新的环境,可是执行sqlplus / as s ...