抄自:http://blog.csdn.net/coldef/article/details/61412577

当时看了就不会,看了别人的题解不懂怎么维护,最后抄了个代码.......

给定一棵n个点的树,每个点有颜色。m次询问,每次询问一个节点子树中深度和这个点深度之差<=d的点的颜色数量。多组数据,每组n,m<=10^5,总共小于500000

题解:如果不考虑深度,我们可以把相同颜色的节点按照dfs序排序,然后相邻节点在lca处-1,这样求子树和就可以求出答案了。考虑深度,我们就用主席树以深度为时间戳来维护呗。感觉看了原作者的代码学到了很多,原作者用set来维护相邻的相同颜色的节点真的妙。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<set>
#include<algorithm>
#define mp(x,y) make_pair
#define pa pair<int,int>
#define itr set<pair<int,int> >::iterator
#define MAXN 100000
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} int n,m,cnt,cc,dfn,head[MAXN+],p[MAXN+];
int fa[MAXN+][],rt[MAXN+],dep[MAXN+],nl[MAXN+],nr[MAXN+],col[MAXN+];
struct TREE{
int l,r,x,lt,rt;
}T[];
vector<int> v[MAXN+];
set<pa > ev[MAXN+];
struct edge{
int to,next;
}e[*MAXN+];
inline void ins(int f,int t){e[++cc].next=head[f];head[f]=cc;e[cc].to=t;}
bool cmp(int x,int y){return nl[x]<nl[y];}
bool cmp2(int x,int y){return dep[x]<dep[y];} void dfs(int x,int d)
{
dep[x]=d;nl[x]=++dfn;
for(int i=head[x];i;i=e[i].next)dfs(e[i].to,d+);
nr[x]=dfn;
} int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);int th=dep[x]-dep[y];
for(int i=;th;th>>=,++i)if(th&)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][];
} void renew(int x0,int&x,int k,int ad,int l,int r)
{
// cout<<"renew"<<x0<<" "<<x<<" "<<k<<" "<<ad<<" "<<l<<" "<<r<<endl;
x=++cnt;T[x].lt=T[x0].lt;T[x].rt=T[x0].rt;
T[x].l=l;T[x].r=r;T[x].x=T[x0].x+ad;
if(l==r)return;int mid=(l+r)>>;
if(k<=mid)renew(T[x0].lt,T[x].lt,k,ad,l,mid);
else renew(T[x0].rt,T[x].rt,k,ad,mid+,r);
} int query(int k,int l,int r)
{
//cout<<"query"<<k<<" "<<l<<" "<<r<<endl;
if(!k)return ;
if(T[k].l==l&&T[k].r==r)return T[k].x;
int mid=(T[k].l+T[k].r)>>;
if(r<=mid)return query(T[k].lt,l,r);
else if(l>mid) return query(T[k].rt,l,r);
else return query(T[k].lt,l,mid)+query(T[k].rt,mid+,r);
} int main()
{
int T=read();
for(int i=;i<=T;i++)
{
cnt=cc=dfn=;for(int i=;i<=n;i++)v[i].clear();
memset(head,,sizeof(head));memset(rt,,sizeof(rt));n=read();m=read();
for(int i=;i<=n;i++){col[i]=read();}
for(int i=;i<=n;i++){fa[i][]=read();ins(fa[i][],i);}
dfs(,);
for(int i=;i<;i++)for(int j=;j<=n;j++)
fa[j][i]=fa[fa[j][i-]][i-];
for(int i=;i<=n;i++)p[i]=i;sort(p+,p+n+,cmp2);
for(int i=;i<=n;i++)
{
int x=p[i],y=p[i-];
renew(rt[dep[y]],rt[dep[x]],nl[x],,,n);
if(ev[col[x]].empty()){ev[col[x]].insert(pa(nl[x],x));continue;}
ev[col[x]].insert(pa(nl[x],x));
itr it=ev[col[x]].find(pa(nl[x],x));
itr a=--it;it=ev[col[x]].find(pa(nl[x],x));itr b=++it;
if(a!=ev[col[x]].end()&&b!=ev[col[x]].end())renew(rt[dep[x]],rt[dep[x]],nl[lca(a->second,b->second)],,,n);
if(a!=ev[col[x]].end())renew(rt[dep[x]],rt[dep[x]],nl[lca(x,a->second)],-,,n);
if(b!=ev[col[x]].end())renew(rt[dep[x]],rt[dep[x]],nl[lca(x,b->second)],-,,n);
}
int last=;
for(int i=;i<=n;i++)ev[i].clear();
for(int i=;i<=m;i++)
{
int u=read()^last,v=read()^last;
last=query(rt[min(dep[p[n]],dep[u]+v)],nl[u],nr[u]);
printf("%d\n",last);
}
}
return ;
}

我好菜啊都不会。

[bzoj省选十连测推广赛2]T2七彩树的更多相关文章

  1. [BZOJ]2017省队十连测推广赛1 T2.七彩树

    题目大意:给你一棵n个点的树,每个点有颜色,m次询问,每次询问一个点x的子树内深度不超过depth[x]+d的节点的颜色数量,强制在线.(n,m<=100000,多组数据,保证n,m总和不超过5 ...

  2. bzoj省选十连测推广赛

    A.普通计算姬 题意:给丁一棵树,每个点有一个权值,用sum(x)表示以x为根的子树的权值和,要求支持两种操作: 1 u v  :修改点u的权值为v. 2 l  r   :  求∑sum[i] l&l ...

  3. [BZOJ]2017省队十连测推广赛1

    听学长说有比赛就随便打一打. A.普通计算姬 题目大意:给出一棵带权树,支持一下两种操作:1.修改一个点的权值:2.给出l,r,询问以点l为根的子树和.点l+1为根的子树和.点l+2为根的子树和--点 ...

  4. 【省选十连测之九】【DP】【组合计数去重】【欧拉函数】基本题

    目录 题意: 输入格式: 输出格式: 数据范围: 思路: 嵌套题的转移 基本题的转移 Part1 Part2 Part3 代码 题意: 这是一个关于括号组合的题. 首先定义一道题是由'(',')',' ...

  5. 【省选十连测之一】【线段树】【最小生成树之Kruskal】公路建设

    目录 题意 输入格式 输出格式 数据范围 思路 代码 题意 有n个点,m条双向道路,其中第条公路的两个端点是u[i],v[i],费用是c[i]. 现在给出q个询问,每次给定一个L和一个R,要求你只能够 ...

  6. 【正睿oi省选十连测】第一场

    四小时写了两个暴力??自闭 [原来这就是神仙们的分量Orz rank 56/75 可以说是无比垃圾了 下周目标:进步十名?[大雾 T1 题意:有n个点的图 点有点权Ai 也有点权Bi = A_1 + ...

  7. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  8. bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 66  Solved: 37[Submit][St ...

  9. ZROI2019 提高十连测

    额 掰手指头一数 特么又是第三年十连测了= = 2017一场没打 那时候好像一场比赛也就100人左右 2018前几场还都好好补了 后来开始放飞自我了 这时候一场有150人还多了 2019想让今年的No ...

随机推荐

  1. 自主学习之RxSwift(一) -----Driver

    对于RxSwift,我也是初学者,此系列来记录我学习RxSwift的历程! (一) 想必关于Drive大家一定在RxSwift的Demo中看到过,也一定有些不解,抱着一起学习的态度,来了解一下Driv ...

  2. nyoj 移位密码

    移位密码 时间限制:1000 ms  |  内存限制:65535 KB 难度:0   描述 移位密码是最简单的一类代替密码,具体算法就是将字母表的字母右移k个位置(k<26),并对字母表长度作模 ...

  3. CentOS7 防火墙firewalld详细操作

    1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld  停止: systemctl disab ...

  4. 【深度学习】深入理解ReLU(Rectifie Linear Units)激活函数

    论文参考:Deep Sparse Rectifier Neural Networks (很有趣的一篇paper) Part 0:传统激活函数.脑神经元激活频率研究.稀疏激活性 0.1  一般激活函数有 ...

  5. 第二章 初识JSP

    第二章   初识JSP 一.JSP简述 1.是JSP JSP是指在HTML中嵌入Java脚本语言.全称(Java Server Pages) 当用户通过浏览器访问Web应用时,使用JSP容器对请求的J ...

  6. SpringBoot入门:Spring Data JPA 和 JPA(理论)

    参考链接: Spring Data JPA - Reference Documentation Spring Data JPA--参考文档 中文版 纯洁的微笑:http://www.ityouknow ...

  7. 新概念英语(1-49)At the butcher's

    新概念英语(1-49)At the butcher's What does Mr. Bird like? A:Do you want any meat today, Mrs. Bird? B:Yes, ...

  8. Python 爬取淘宝商品信息和相应价格

    !只用于学习用途! plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html) :获得商品价格和view_pri ...

  9. DevExpress控件的GridControl实现行多选

    最近用到DevExpress控件的GridControl控件,需要用到行多选的操作,在网上找的资料,自己总结一下. 先展示一下效果:

  10. Linux命令(持续更新中)

    命令名 用法 安装上传下载 yum install lrzsz   rz上传文件,sz下载文件 压缩 解压文件 tar -zxvf  文件名 压缩文件 tar -zcvf 文件名 删除非空目录: rm ...