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 ...
随机推荐
- HTML5+规范:nativeUI(管理系统原生界面)
nativeUI管理系统原生界面,可用于弹出系统原生提示对话框窗口.时间日期选择对话框.等待对话框等. 1.方法 1.1.actionSheet: 弹出系统选择按钮框 void plus.native ...
- Drool7s 什么叫KIE和生命周期-系列03课
KIE是缩写,knowledge is everything.可以理解成一个上层接口,本质是由很多个实现类去实现功能的. 另外关于drool7s的生命周期,请看下图 本文只是让你了解drools7的一 ...
- 4.将验证添加到 ASP.NET Core Razor 页面
向 Movie 模型添加了验证逻辑. 每当用户创建或编辑电影时,都会强制执行验证规则. 1.打开Movie.cs文件.DataAnnotations命名空间提供了一组内置的验证属性,这些属性以声明方式 ...
- ABP 结合 MongoDB 集成依赖注入
1.我们再ABP项目添加一个.NET Core类库 类库名自定定义, 我这里定义为 TexHong_EMWX.MongoDb 添加NuGet包. ABP mongocsharpdriver 添加 A ...
- 在ASP.NET MVC中加载部分视图的方法及差别
在视图里有多种方法可以加载部分视图,包括Partial() .Action().RenderPartial().RenderAction().RenderPage()方法.下面说明一下这些方法的差别. ...
- Tomcat组件梳理--Server
Tomcat组件梳理--Server 1.Server组件的定义和功能概述 定义: Server组件用于描述一个启动的Tomcat实例,一个Tocmat被启动,在操作系统中占用一个进程号,提供web服 ...
- Java自学-控制流程 break
Java的break语句 结束循环 示例 1 : break; 直接结束当前for循环 public class HelloWorld { public static void main(String ...
- 【转载】 C#使用Newtonsoft.Json组件来反序列化字符串为对象
在Asp.Net网站开发的过程中,很多时候会遇到对象的序列化和反序列化操作,Newtonsoft.Json组件是专门用来序列化和反序列化操作的一个功能组件,引入这个DLL组件后,就可使用JsonCon ...
- Radmin入侵
Radmin (Remote Administrator)是一款屡获殊荣的远程控制软件,它将远程控制.外包服务组件.以及网络监控结合到一个系统里,提供目前为止最快速.强健而安全的工具包 生成被控端 点 ...
- Devops Reference
摘自 https://www.cnblogs.com/yibutian/p/9561657.html DevOps 企业实践 实施DevOps的核心目标是加速团队.企业的IT精益运行,从根本上提升IT ...