题目大意:

给定一颗树,询问树中某个点x的子树中与其距离不超过d的所有点中本质不同的颜色数
强制在线

题解:

一下午终于把这道题叉掉了。

写了三个算法,前两个都是错的,后一个是%的网上大爷们的题解.

首先我们发现这道题有一个特点:没有修改操作 !!
这就使我们能够对颜色进行预处理。
所以我们可以考虑分别枚举每个颜色,对其去重后更新树上的信息。
所以我们可以考虑树链的并,我们可以对每种颜色都做一遍树链的并
容易发现复杂度仍然是\(O(nlogn)\)的
但是这样我们只求出来的每个节点子树中不同的颜色的个数
并没有满足对深度的限制
弱弱的我想到这里就继续不下去了,不知道下面改怎么写,YY了两个算法
第一个算法打着打着感觉不对,(Ctrl+A) + (Backspace)
第二个算法打出来了调样例,手模一下发现算法是错的.(Alt+F4)


去%了大爷们的题解:

我们把所有的点按照深度动态地进行树链的并.
这样,我们就发现我们实际上可以求出每一个深度到树根中不同颜色的种类
但是我们发现我们单单考虑了深度的一个边界还没有结束.
我们还需要限制深度另一个边界和在x子树中的限制
我们发现其实这两个限制等价于dfs序在x的子树dfs序范围之间.
所以。。。在深度上用线段树可持久化即可...

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std;
typedef long long ll;
inline void read(int &x){x=0;char ch;bool flag = false;while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
struct Edge{int to,next;
}G[maxn<<2];
int head[maxn],cnt;
void add(int u,int v){G[++cnt].to = v;G[cnt].next = head[u];head[u] = cnt;
}
int dfn[maxn],dfs_clock,son[maxn],siz[maxn];
int dep[maxn],top[maxn],fa[maxn],oud[maxn];#define v G[i].to
void dfs(int u){siz[u] = 1;for(int i = head[u];i;i=G[i].next){if(v == fa[u]) continue;fa[v] = u;dep[v] = dep[u] + 1;dfs(v);siz[u] += siz[v];if(siz[son[u]] < siz[v]) son[u] = v;}
}
void dfs(int u,int tp){top[u] = tp;dfn[u] = ++dfs_clock;if(son[u]) dfs(son[u],tp);for(int i = head[u];i;i=G[i].next){if(v == fa[u] || v == son[u]) continue;dfs(v,v);}oud[u] = dfs_clock;
}
#undef v
inline int lca(int u,int v){while(top[u] != top[v]){if(dep[top[u]] < dep[top[v]]) swap(u,v);u = fa[top[u]];}return dep[u] < dep[v] ? u : v;
}
int col[maxn],n;
namespace Trp{struct Node{Node *ch[2];int dfn,siz,fix,id;void update(){siz = ch[0]->siz + ch[1]->siz + 1;}}mem[maxn<<2],*it,*null,*root[maxn];inline void init(){it = mem;null = it++;null->ch[0] = null->ch[1] = 0;null->id = -1;null->dfn = null->siz = 0;}inline Node* newNode(int x,int i){Node *p = it++;p->ch[0] = p->ch[1] = null;p->dfn = x;p->fix = rand();p->siz = 1;p->id = i;return p;}void rotate(Node* &p,int k){Node *y = p->ch[k^1];p->ch[k^1] = y->ch[k];y->ch[k] = p;p->update();y->update();p = y;}void insert(Node* &p,int x,int id){if(p == null) p = newNode(x,id);else{insert(p->ch[p->dfn < x],x,id);p->update();if(p->ch[p->dfn<x]->fix < p->fix)rotate(p,p->dfn > x);}}inline int find(int k,Node *root){Node *p = root;if(k < 1 || k > p->siz) return -1;while(p != null){if(p->ch[0]->siz + 1 == k) return p->id;if(p->ch[0]->siz + 1 > k) p = p->ch[0];else k -= p->ch[0]->siz + 1,p = p->ch[1];}assert(0);}inline int rank(int d,Node* root){int ret = 1;Node *p = root;while(p != null){if(p->dfn < d) ret += p->ch[0]->siz + 1,p = p->ch[1];else p = p->ch[0];}return ret;}
}
namespace seg{struct Node{Node* ch[2];int val;void update(){val = ch[0]->val + ch[1]->val;}}mem[maxn*100],*it,*null,*root[maxn];inline void init(){it = mem;null = it++;null->ch[0] = null->ch[1] = null;null->val = 0;root[0] = null;}Node* insert(Node *rt,int l,int r,int pos,int w){Node *p = it++;*p = *rt;if(l == r){p->val += w;return p;}int mid = l+r >> 1;if(pos <= mid) p->ch[0] = insert(p->ch[0],l,mid,pos,w);else p->ch[1] = insert(p->ch[1],mid+1,r,pos,w);p->update();return p;}int query(Node *p,int l,int r,int L,int R){if(L <= l && r <= R) return p->val;int mid = l+r >> 1;if(R <= mid) return query(p->ch[0],l,mid,L,R);if(L >  mid) return query(p->ch[1],mid+1,r,L,R);return query(p->ch[0],l,mid,L,R) + query(p->ch[1],mid+1,r,L,R);}
}
int q[maxn],l,r,mx;
inline void bfs(){l = 0;r = -1;q[++r] = 1;while(l <= r){int u = q[l++],x = Trp::rank(dfn[u],Trp::root[col[u]]),y,z;mx = max(mx,dep[u]);seg::root[dep[u]] = seg::insert(seg::root[dep[q[l-2]]],1,n,dfn[u],1);Trp::insert(Trp::root[col[u]],dfn[u],u);y = Trp::find(x-1,Trp::root[col[u]]);z = Trp::find(x+1,Trp::root[col[u]]);if(y != -1 && z != -1){int lc = lca(y,z);seg::root[dep[u]] = seg::insert(seg::root[dep[u]],1,n,dfn[lc],1);}if(y != -1){int lc = lca(y,u);seg::root[dep[u]] = seg::insert(seg::root[dep[u]],1,n,dfn[lc],-1);}if(z != -1){int lc = lca(z,u);seg::root[dep[u]] = seg::insert(seg::root[dep[u]],1,n,dfn[lc],-1);}for(int i = head[u];i;i=G[i].next){int v = G[i].to;if(v == fa[u]) continue;q[++r] = v;}}
}
inline void init(){memset(head,0,sizeof head);cnt = 0;memset(son,0,sizeof son);memset(siz,0,sizeof siz);dfs_clock = 0;mx = 0;
}
int main(){int T;read(T);srand(6613);while(T--){init();seg::init();Trp::init();int m;read(n);read(m);for(int i=0;i<=n;++i){Trp::root[i] = Trp::null;seg::root[i] = seg::null;}for(int i=1;i<=n;++i) read(col[i]);for(int i=2;i<=n;++i){read(fa[i]);add(fa[i],i);}dfs(1);dfs(1,1);bfs();int ans = 0;int x,d;while(m--){read(x);read(d);x ^= ans;d ^= ans;int de = dep[x] + d;if(de > mx) de = mx;ans = seg::query(seg::root[de],1,n,dfn[x],oud[x]);printf("%d\n",ans);}}getchar();getchar();return 0;
}

转载于:https://www.cnblogs.com/Skyminer/p/6556815.html

bzoj 4771: 七彩树 树链的并+可持久化线段树相关推荐

  1. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

  2. [BZOJ 3207] 花神的嘲讽计划Ⅰ【Hash + 可持久化线段树】

    题目链接:BZOJ - 3207 题目分析 先使用Hash,把每个长度为 k 的序列转为一个整数,然后题目就转化为了询问某个区间内有没有整数 x . 这一步可以使用可持久化线段树来做,虽然感觉可以有更 ...

  3. [APIO2017]斑斓之地——可持久化线段树

    题目链接: [APIO2017]斑斓之地 将不是河流的格子染成白色,是河流的格子染成黑色,那么连通块数就是白色格子数$-1*2$的联通白色格子数$-2*1$的联通白色格子数$+2*2$的联通白色格子数 ...

  4. loj6169 相似序列(可持久化线段树)

    题目: https://loj.ac/problem/6169 分析: 如果是要求两段序列全等的话,有一个套路: 对于{a1,a2,a3} {a4,a5,a6} 设一个素数p,那么如果p^a1+p^a ...

  5. BZOj #4771. 七彩树(主席树+dfn序+lca)

    BZOj #4771. 七彩树 description solution code description 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色, ...

  6. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

  7. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  8. BZOJ 4408: [Fjoi 2016]神秘数(可持久化线段树)

    题目描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4408 题目大意:求最小不能被一段区间中某些数的和表示的数.(还是看题面吧) 思路 可持久化 ...

  9. 【GDOI2016】疯狂动物城(树链剖分+可持久化线段树)

    码农题- 调了我三个晚上- 看来我的代码能力还是太弱了- 首先我们不难发现在u到v这条链的答案为∑i=1n(n−i)(n−i+1)ai2\sum_{i=1}^n\frac{(n-i)(n-i+1)a_ ...

最新文章

  1. 如何周密规划决策制定过程
  2. java打开文件出错_打开文件错误太多,java.io.FileNotFoundException
  3. 十一、python生成器和迭代器
  4. python3  循环输出当前时间。
  5. conda报错Collecting package metadata
  6. imageJ 如何下载plugin_如何给微服务架构的项目做验收测试?
  7. c/c++线性循环队列
  8. 2022年武汉CMMI3-CMMI5认证企业名录
  9. SLAM十四讲中的第五讲点云拼接
  10. 华三交换机ping大包命令_华三(H3C)交换机命令大全
  11. 创建Image图像的几种方法
  12. android项目版本,怎查看Android项目的Android版本
  13. PE——滴水的壳项目
  14. 【C++进阶:二叉树进阶】二叉搜索树的操作和key模型、key/value模型的实现 | 二叉搜索树的应用 | 二叉搜索树的性能分析
  15. 原生ajax传值php,原生ajax上传图片,php后台处理总结
  16. 解决模拟器方向键无法使用问题
  17. 网游、链游、电子竞技是网络中的艺术吗?
  18. NASA教你攒火星探测器,连购物车都加好了
  19. python:print函数打印空行
  20. CSS line-height与vertical-align

热门文章

  1. python爬虫抓取信息_python爬虫爬取网上药品信息并且存入数据库
  2. 计算机原理说课教案,《 计算机组成原理 》 说课
  3. python中的列表生成式_Python中的列表生成式
  4. 蔡明机器人对比_“百变”蔡明:一个拥有性感身材的“小品天后”!
  5. android 程序 读logo,Android端APP更换logo和名称后都需要些测试哪些内容呢?
  6. 反arp攻击软件_谈谈电子欺骗中的ARP欺骗
  7. Acwing--朴素dijkstra
  8. php计算属相,一个判断干支、属相和星座的php函数
  9. java aqs源码_Java-AQS源码详解(细节很多!)
  10. Fins TCP协议