正题

题目链接:https://www.luogu.com.cn/problem/P6177


题目大意

nnn个点的一棵树mmm次询问树上颜色。
强制在线

1≤n≤4×105,1≤m≤105,0≤vali<2311\leq n\leq 4\times 10^5,1\leq m\leq 10^5,0\leq val_i<2^{31}1≤n≤4×105,1≤m≤105,0≤vali​<231


解题思路

把所有深度为n\sqrt nn​并且下面至少有n\sqrt nn​的深度的点标记,这样保证关键点数量不超过n\sqrt nn​。

然后每个点到他周围关键点的距离也不会超过 n\sqrt nn​ 。

这样可以处理出关键点两两之间的颜色bitsetbitsetbitset,然后每次路径找两个最近的关键点爆做就好了。

时间复杂度O((m+n)(n+nω))O((m+n)(\sqrt n+\frac{n}{\omega}))O((m+n)(n​+ωn​))


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cmath>
using namespace std;
const int N=41000,T=300,M=(4e4)/T+10;
struct node{int to,next;
}a[N<<1];
int n,m,tot,cnt,sum,fa[N],v[N],top[N],ls[N],d[N],dep[N],w[N],b[N],mark[N],dfn[N],ed[N],g[M][M];
bitset<N> f[M][M],bt;
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(int x){for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x])continue;dep[y]=dep[x]+1;fa[y]=x;dfs(y);d[x]=max(d[x],d[y]+1);}if(dep[x]%T==0&&d[x]>=T)mark[x]=++cnt;return;
}
void dFs(int x){if(mark[x])top[x]=x;dfn[x]=++cnt;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x])continue;top[y]=top[x];dFs(y);}ed[x]=cnt;return;
}
void calc(int x,int p,int fa){if(!v[w[x]])bt[w[x]]=1,sum++;v[w[x]]++;if(mark[x])f[p][mark[x]]=bt,g[p][mark[x]]=sum;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa)continue;calc(y,p,x);}v[w[x]]--;if(!v[w[x]])bt[w[x]]=0,sum--;return;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&w[i]),b[i]=w[i];sort(b+1,b+1+n);int L=unique(b+1,b+1+n)-b-1;for(int i=1;i<=n;i++)w[i]=lower_bound(b+1,b+1+L,w[i])-b;for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs(1);cnt=0;dFs(1);for(int i=1;i<=n;i++)if(mark[i])calc(i,mark[i],i);int last=0;while(m--){int x,y;scanf("%d%d",&x,&y);x^=last;if(top[x]==top[y]){int xx=x,yy=y,ans=0;while(x!=y){if(dep[x]<dep[y])swap(x,y);if(!v[w[x]])ans++,v[w[x]]=1;x=fa[x];}if(!v[w[x]])ans++,v[w[x]]=1;printf("%d\n",ans);last=ans;x=xx;y=yy;while(x!=y){if(dep[x]<dep[y])swap(x,y);v[w[x]]=0;x=fa[x];}v[w[x]]=0;}else{if(dfn[x]>=dfn[y]&&dfn[x]<=ed[y])swap(x,y);if(dfn[y]>=dfn[x]&&dfn[y]<=ed[x]){int z=top[y];while(top[fa[z]]!=top[x])z=top[fa[z]];bt=f[mark[z]][mark[top[y]]];int ans=g[mark[z]][mark[top[y]]];while(y!=top[y]){if(!bt[w[y]])ans++,bt[w[y]]=1;y=fa[y];}while(z!=x){if(!bt[w[z]])ans++,bt[w[z]]=1;z=fa[z];}if(!bt[w[z]])ans++,bt[w[z]]=1;printf("%d\n",ans);last=ans;}else{bt=f[mark[top[x]]][mark[top[y]]];int ans=g[mark[top[x]]][mark[top[y]]];while(x!=top[x]){if(!bt[w[x]])ans++,bt[w[x]]=1;x=fa[x];}while(y!=top[y]){if(!bt[w[y]])ans++,bt[w[y]]=1;y=fa[y];}printf("%d\n",ans);last=ans;}}}return 0;
}

P6177-Count on a tree II/[模板]树分块相关推荐

  1. SP10707 COT2 - Count on a tree II

    SP10707 COT2 - Count on a tree II 题意: 给定 n 个结点的树,每个结点有一种颜色. m 次询问,每次询问给出 u,v,回答 u,v 之间的路径上的结点的不同颜色数. ...

  2. 【莫队/树上莫队/回滚莫队】原理详解及例题:小B的询问(普通莫队),Count on a tree II(树上莫队),kangaroos(回滚莫队)

    文章目录 问题引入 介绍莫队算法及其实现过程 时间复杂度 莫队算法适用范围 莫队奇偶优化 普通莫队:小B的询问 树上莫队:SP10707 COT2 - Count on a tree II 回滚莫队: ...

  3. 【SPOJ】Count On A Tree II(树上莫队)

    [SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...

  4. BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树

    BZOJ 2588 Count on a tree 题面 求树上两点之间路径上第k大的点权. 题解 一开始看到这道题觉得是树剖,然后又听说是主席树,然后以为是主席树+树剖,差点没吓死-- 然后发现,如 ...

  5. BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...

  6. SPOJ - COT Count on a tree [LCA+主席树]【数据结构】

    题目链接:http://www.spoj.com/problems/COT/en/ -------------------------------------- COT - Count on a tr ...

  7. SPOJ - COT Count on a tree(LCA+主席树+离散化)

    题目链接:点击查看 题目大意:给出一棵树,每个点都有一个权值,现在给出m个询问,每次询问的格式是u,v,k,要求输出u-v这条路径上第k大的数 题目分析:一看到第k大的数就会想到主席树,既然是在树上的 ...

  8. SPOJ COT Count on a tree(主席树+倍增lca)

    思路:这个题其实就是树上的第k小,主席树的本质还是类似于前缀和一样的结构,所以是完全相同的,所以我们在树上也可以用同样的方法,我们对于每一个节点进行建树,然后和普通的树上相同,ab之间的距离是等于 r ...

  9. 【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA

    传送门 写在前面:一天下来就写了两道主席树的题--(codevs上的一道智障天梯不算) 思路: 才知道原来主席树不仅可以通过dfs序维护子树区间,还可以直接维护一条到根的链-- 我们建好主席树后,每次 ...

最新文章

  1. R语言merge函数左连接dataframe数据(Left (outer) join in R)、左连接必须将参数all设置(all.x = TRUE)、默认merge函数通过公共列名合并数据集
  2. CUR分解算法及Python实现
  3. qsort()与sort的用法(收藏)
  4. linux下编译的PHP添加soap扩展
  5. macOS查看IP地址的命令
  6. 基于IMAGE法的房间回响模型创建、C++代码实现、matlab仿真
  7. 微服务框架 Spark Framework
  8. move语句java_java自动化代码优化
  9. YUI3学习笔记 ( 8 )
  10. RabbitMQ架构模型(一)
  11. 2017年(毕业生)暑期实习信息汇总
  12. 计算机安全覆盖的内容有哪些,计算机网络的分类有哪些
  13. 人工智能机器学习笔记 10月10日
  14. Linux 内核第一宏
  15. java开发常用的linux命令,Java开发中最常用的Linux命令整理
  16. 如何录制游戏视频 电脑屏幕录制的方法
  17. 全国计算机信息安全技术
  18. 思源黑体官方下载地址
  19. 银河麒麟V10服务器系统安装教程及注意事项
  20. 为什么alert没有弹窗?

热门文章

  1. oracle中触发器只能用于表吗,Oracle触发器的分类和使用
  2. clover 主题_Clover主题更换
  3. 你真的知道Java同步锁何时释放?
  4. java 日期 区间_如何实现时间区间的分割??
  5. 计算数字的出现次数 java_关于Java:如何计算数字在.txt文件中出现的次数
  6. mfc从mysql中读取数据类型_在MFC中使用SQlite数据库读取数据
  7. 经纬度 c代码中定义_如何将TXT文本格式的批量经纬度值导入到奥维成为标签
  8. 此 sqltransaction 已完成;它再也无法使用_手把手教你如何修眉毛,学会再也不用花钱去美容院了...
  9. mac 配置php和mysql_Mac下配置PHP+MySql环境
  10. php多进程 写入文件_PHP多进程中使用file_put_contents安全吗?