题意:求一条链 \((u,v)\) 上不同的颜色数。

我们可以求出树的出栈入栈序(or 括号序?我也不确定)。

图(from attack

然后有一个很优美的性质:

设点 \(u\) 的入栈时间为 \(dfn[u]\) ,出栈时间为 \(low[u]\)

设两个点 \(u,v\) 满足 \(dfn[u]<dfn[v]\)

若 \(u\) 为 \(v\) 的 \(lca\),那么我们只需查询 \([dfn[u],dfn[v]]\) 中只出现一次的点有多少不同的颜色。

若 \(u\) , \(v\) 不在一个子树中,我们只需查询 \([low[u],dfn[v]]\) 中只出现一次的点有多少不同的颜色,并单独检查 \(lca\) 的颜色。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<vector>
  7. #define R register int
  8. using namespace std;
  9. namespace Luitaryi {
  10. inline int g() { R x=0,f=1;
  11. register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
  12. do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
  13. } const int N=200010,M=200010; bool vis[N];
  14. int n,m,B,cnt,num,mem[N<<1],pos[N<<1],a[N],b[N],c[N],ans[N],tot;
  15. int vr[N<<1],nxt[N<<1],fir[N],dfn[N],low[N],pre[N],top[N],sz[N],son[N],d[N];
  16. inline void add(int u,int v) {
  17. vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;
  18. vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt;
  19. }
  20. inline void dfs(int u) { sz[u]=1,dfn[u]=++num,mem[num]=u;
  21. for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
  22. if(d[v]) continue; pre[v]=u,d[v]=d[u]+1,dfs(v);
  23. if(sz[son[u]]<sz[v]) son[u]=v; sz[u]+=sz[v];
  24. } low[u]=++num,mem[num]=u;
  25. }
  26. inline void dfs2(int u,int tp) { top[u]=tp;
  27. if(son[u]) dfs2(son[u],tp);
  28. for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
  29. if(v!=son[u]&&v!=pre[u]) dfs2(v,v);
  30. }
  31. }
  32. inline int lca(int u,int v) {
  33. for(;top[u]!=top[v];u=pre[top[u]]) if(d[top[u]]<d[top[v]]) swap(u,v);
  34. return d[u]<d[v]?u:v;
  35. }
  36. struct node {int l,r,op,id;
  37. inline bool operator < (const node& that) const
  38. {return pos[l]==pos[that.l]?(pos[l]&1)?r<that.r:r>that.r:l<that.l;}
  39. }q[M];
  40. inline void add(int x) {if(++c[x]==1) ++tot;}
  41. inline void sub(int x) {if(--c[x]==0) --tot;}
  42. inline void f(int u) {vis[u]?sub(a[u]):add(a[u]); vis[u]^=1;}
  43. inline void main() {
  44. n=g(),m=g(); B=sqrt(n);
  45. for(R i=1;i<=n;++i) a[i]=g();
  46. memcpy(b,a,sizeof b);
  47. sort(b+1,b+n+1); R t=unique(b+1,b+n+1)-b-1;
  48. for(R i=1;i<=n;++i) a[i]=lower_bound(b+1,b+t+1,a[i])-b;
  49. for(R i=1,u,v;i<n;++i) u=g(),v=g(),add(u,v); d[1]=1,dfs(1),dfs2(1,1);
  50. for(R i=1,u,v,l;i<=m;++i) {
  51. u=g(),v=g(),l=lca(u,v);
  52. if(dfn[u]>dfn[v]) swap(u,v);
  53. if(l==u) q[i]=(node){dfn[u],dfn[v],0,i};
  54. else q[i]=(node){low[u],dfn[v],l,i};
  55. } for(R i=1;i<=2*n;++i) pos[i]=(i-1)/B+1;
  56. sort(q+1,q+m+1);
  57. for(R i=1,l=1,r=0,op,LL,RR,id;i<=m;++i) {
  58. LL=q[i].l,RR=q[i].r,op=q[i].op,id=q[i].id;
  59. while(l<LL) f(mem[l++]);
  60. while(l>LL) f(mem[--l]);
  61. while(r<RR) f(mem[++r]);
  62. while(r>RR) f(mem[r--]);
  63. ans[id]=tot+(op&&c[a[op]]==0);
  64. } for(R i=1;i<=m;++i) printf("%d\n",ans[i]);
  65. }
  66. } signed main() {Luitaryi::main(); return 0;}

2019.11.21

SP10707 COT2 - Count on a tree II 莫队上树的更多相关文章

  1. SP10707 COT2 - Count on a tree II 莫队

    链接 https://vjudge.net/problem/SPOJ-COT2 https://www.luogu.org/problemnew/show/SP10707 思路 dfs欧拉序转化为普通 ...

  2. SP10707 COT2 - Count on a tree II (树上莫队)

    大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...

  3. SP10707 COT2 - Count on a tree II [树上莫队学习笔记]

    树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...

  4. [SP10707]COT2 - Count on a tree II

    题目大意:有一棵$n$个节点的树,第$i$个点有一个颜色$C_i$,$m$组询问,每次问$x->y$的路径上有多少种颜色 题解:树上莫队,把树按欧拉序展开成一条链,令第$i$个节点第一次出现在序 ...

  5. SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)

    COT2 - Count on a tree II #tree You are given a tree with N nodes. The tree nodes are numbered from  ...

  6. COT2 - Count on a tree II(树上莫队)

    COT2 - Count on a tree II You are given a tree with N nodes. The tree nodes are numbered from 1 to N ...

  7. spoj COT2 - Count on a tree II

    COT2 - Count on a tree II http://www.spoj.com/problems/COT2/ #tree You are given a tree with N nodes ...

  8. 【SPOJ10707】 COT2 Count on a tree II

    SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...

  9. 【树上莫队】【SP10707】 COT2 - Count on a tree II

    Description 给定一棵 \(n\) 个点的树,每个节点有一个权值,\(m\) 次询问,每次查询两点间路径上有多少不同的权值 Input 第一行是 \(n\) 和 \(m\) 第二行是 \(n ...

随机推荐

  1. pyenv基本使用

    pyenv使用 1.安装: git clone https://github.com/pyenv/pyenv.git 2.配置pyenv环境变量 echo 'export PYENV_ROOT=&qu ...

  2. FIFO形成3x3矩阵

    Verilog生成矩阵一般是使用shift_ip核,但其实用两个FIFO也行.最近刚好学到这种方法,把原理总结一下. 要求 现在有10x5的数据和对应数据有效指示信号,数据为0~49,要用FPGA对其 ...

  3. (三)pdf的构成之文件头综述

    引自:https://blog.csdn.net/steve_cui/article/details/81981943 一般情况下,文件头,即,PDF文件的第一行,它用来定义PDF的版本,从而确定该P ...

  4. python_二叉树简单实现

    今日头条面试题,先做下: 二叉树代码实现 class Node: def __init__(self,item): self.item = item self.child1 = None self.c ...

  5. Spring Cloud Alibaba学习笔记(22) - Nacos配置管理

    目前业界流行的统一配置管理中心组件有Spring Cloud Config.Spring Cloud Alibaba的Nacos及携程开源的Apollo,本文将介绍Nacos作为统一配置管理中心的使用 ...

  6. C# 使用代理实现方法过滤

    一.为什么要进行方法过滤 一些情况下我们需要再方法调用前记录方法的调用时间和使用的参数,再调用后需要记录方法的结束时间和返回结果,当方法出现异常的时候,需要记录异常的堆栈和原因,这些都是与业务无关的代 ...

  7. C盘清理、C盘瘦身、省出30G

    三招C盘瘦身30G,清理win10系统中虚占C盘空间的三大祸害 1.对C盘进行“磁盘清理” C盘右键->属性->磁盘清理->清理系统文件->勾选“windows更新清理”-&g ...

  8. python3-使用requests模拟登录网易云音乐

    # -*- coding: utf-8 -*- from Crypto.Cipher import AES import base64 import random import codecs impo ...

  9. UnicodeDecodeError: 'utf-8' codec can't decode byte..问题

    解决UnicodeDecodeError: 'utf-8' codec can't decode byte..问题 问题描述: 问题分析: 该情况是由于出现了无法进行转换的 二进制数据 造成的,可以写 ...

  10. HTML5新增元素和移除的元素?

    新增元素: 图像Canvas 多媒体video.audio 本地存储localStorage.sessionStorage 语义化更好的内容元素aticle.header.footer.nav.sec ...