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 ...
随机推荐
- CF933E A Preponderant Reunion DP
传送门 题解搬运工 设原问题为问题A.每一次减少\(\min\{p_i , p_{i+1}\}\)难以处理,我们考虑将限制变得宽松一些:每一次可以减少\([1,\min\{p_i , p_{i+1}\ ...
- 【2】【典型一维动态规划】【剑指offer+leetcode53】连续子数组的最大和
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量中包含负数 ...
- (1)ASP.NET Core 应用启动Startup类简介
1.前言 Core与早期版本的 ASP.NET 对比,配置应用程序的方式的 Global.asax.FilterConfig.cs和RouteConfig.cs 都被Program.cs 和 Star ...
- C# vb .net实现负片特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的负片特效呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...
- angular复习笔记2-架构总览
angular架构总览 一个完整的Angular应用主要由6个重要部分构成,分别是:组件.模板.指令.服务.依赖注入和路由.这些组成部分各司其职,而又紧密协作,它们的关系如图所示. 与用户直接交互的是 ...
- P1347 排序 (拓扑排序,tarjan)
题目 P1347 排序 解析 打开一看拓扑排序,要判环. 三种情况 有环(存在矛盾) 没环但在拓扑排序时存在有两个及以上的点入度为0(关系无法确定) 除了上两种情况(关系可确定) 本来懒了一下,直接在 ...
- 安装VMware14可能出现的问题
未能提取文件 安装程序未能提取安装vmware workstation所必须的文件 在没有关闭这个弹框的前提下,Win+R输入%temp%,找到以~setup结尾的文件夹,双击下面的临时文件VMwar ...
- js数组(五)
一.数组的声明方法一:[构造函数形式声明] var array = new Array(); //[] var array = new Array(10); //数组长度:array.length = ...
- js计算hashcode
String.prototype.hashCode = function(){ var hash = 0; for (var i = 0; i < this.length; i++) { var ...
- JavaScript之控制表单元素的值
表单元素.value 获取表单元素的值 表单元素.value='这是修改后的值' 修改表单元素的值 案例: (1)html <input type="text" id=&qu ...