这个思路挺有意思的 ~

利用树链的并来保证每个颜色只贡献一次,然后用可持久化线段树维护

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: 七彩树 可持久化线段树+树链的并的更多相关文章

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

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

  2. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

  3. BZOJ.4771.七彩树(可持久化线段树)

    BZOJ 考虑没有深度限制,对整棵子树询问怎么做. 对于同种颜色中DFS序相邻的两个点\(u,v\),在\(dfn[u],dfn[v]\)处分别\(+1\),\(dfn[LCA(u,v)]\)处\(- ...

  4. bzoj 4771: 七彩树 树链的并+可持久化线段树

    题目大意: 给定一颗树,询问树中某个点x的子树中与其距离不超过d的所有点中本质不同的颜色数 强制在线 题解: 一下午终于把这道题叉掉了. 写了三个算法,前两个都是错的,后一个是%的网上大爷们的题解. ...

  5. BZOJ4771七彩树——可持久化线段树+set+树链的并+LCA

    给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节 点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义dept ...

  6. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  7. bzoj 2653 二分答案+可持久化线段树

    首先离散化,然后我们知道如果对于一个询问的区间[l1,r1],[l2,r2],我们二分到一个答案x,将[l1,r2]区间中的元素大于等于x的设为1,其余的设为-1,那么如果[l1,r1]的最大右区间和 ...

  8. BZOJ 3439 Kpm的MCpassword Trie树+可持久化线段树

    题目大意:给定n个字符串,对于每一个字符串求以这个字符串为后缀的字符串中第k小的编号 首先将字符串反转 那么就变成了对于每一个字符串求以这个字符串为前缀的字符串中第k小的编号 然后考虑对字符串排序 那 ...

  9. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

随机推荐

  1. html 打开新页面

    设置 target 页面 这样会点击一次就产生一个页面 页面 填任意名称,多个点击只产生于一个页面

  2. CentOS7安装rabbitmq集群(二进制)

    一.RabbiMQ简介 RabbiMQ是用Erang开发的,集群非常方便,因为Erlang天生就是一门分布式语言,但其本身并不支持负载均衡. RabbiMQ模式 RabbitMQ模式大概分为以下三种: ...

  3. ubuntu 安装Jenkins

    一.介绍 Jenkins是一款开源自动化服务器,旨在自动化连续集成和交付软件所涉及的重复技术任务. Jenkins是基于Java的,可以从Ubuntu软件包安装,也可以通过下载和运行其Web应用程序A ...

  4. java之mybatis之查询及分页

    1.mybatis中查询方式有3种 //查询单个值 @Test public void testFindOne()throws IOException{ SqlSession session = My ...

  5. python中的{字典}

    目录 字典--dict { } 字典是无序,可变的数据类型. 字典:用于存储数据,存储大量数据,字典要比列表快:将数据和数据之间进行关联. 定义: dic = {键:值,键:值} #每个 键值对 以逗 ...

  6. spring中bean的作用域属性singleton与prototype的区别

    1.singleton 当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会 ...

  7. 图解HTTP(一)

    第一章 了解Web及网络基础 1.为知识共享为规划Web,基本理念是:借助多文档之间相互关联(你中有我,我中有你)形成的超文本,连成客户想参阅的WWW(World Wide Web). 2.提出了3项 ...

  8. 如何在SAP Cloud Platform上进行第一个integration flow开发

    登录SAP Cloud Platform integration tenant,点击Edit图标: 创建一个新的Content package: 保存content package后,点击artifa ...

  9. 基于Text-CNN模型的中文文本分类实战 流川枫 发表于AI星球订阅

    Text-CNN 1.文本分类 转眼学生生涯就结束了,在家待就业期间正好有一段空闲期,可以对曾经感兴趣的一些知识点进行总结. 本文介绍NLP中文本分类任务中核心流程进行了系统的介绍,文末给出一个基于T ...

  10. 安装nginx + nginx-gridfs + mongodb

    1.安装依赖包 yum -y install pcre-devel openssl-devel zlib-devel git gcc gcc-c++ git clone https://github. ...