题目大意:给定一棵 N 个节点的无根树,每个节点有一个颜色。现有 M 个询问,每次询问一条树链上的不同颜色数。

题解:学会了树上莫队。

树上莫队是将节点按照欧拉序进行排序,将树上问题转化成序列上的问题进行求解的算法。需要分两种情况进行讨论,第一种情况是对于询问 x,y 来说,x 为 y 的祖先,则询问的区间为 \(st[x],st[y]\),第二种情况是 x 与 y 处在两个不同的子树内,这时发现 \(lca(x,y)\) 的欧拉序并不在 [ed[x], st[y]] 内,因此需要额外考虑 lca 的贡献。

代码如下

  1. #include <bits/stdc++.h>
  2. #define fi first
  3. #define se second
  4. #define pb push_back
  5. #define mp make_pair
  6. #define all(x) x.begin(),x.end()
  7. #define cls(a,b) memset(a,b,sizeof(a))
  8. using namespace std;
  9. typedef long long ll;
  10. typedef pair<int,int> P;
  11. const int dx[]={0,1,0,-1};
  12. const int dy[]={1,0,-1,0};
  13. const int mod=1e9+7;
  14. const int inf=0x3f3f3f3f;
  15. const int maxn=4e4+10;
  16. const int maxm=1e5+10;
  17. const double eps=1e-6;
  18. inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
  19. inline ll sqr(ll x){return x*x;}
  20. inline ll fpow(ll a,ll b,ll c){ll ret=1%c;for(;b;b>>=1,a=a*a%c)if(b&1)ret=ret*a%c;return ret;}
  21. inline ll read(){
  22. ll x=0,f=1;char ch;
  23. do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
  24. do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
  25. return f*x;
  26. }
  27. /*------------------------------------------------------------*/
  28. vector<int> G[maxn];
  29. int f[maxn][20],dep[maxn],idfn[maxn<<1],st[maxn],ed[maxn],e_clk;
  30. int n,m,a[maxn],d[maxn],tot,bsize;
  31. struct query{int id,bl,l,r,lca;}q[maxm];
  32. bool cmp(const query &x,const query &y){return x.bl!=y.bl?x.bl<y.bl:x.r<y.r;}
  33. inline int get(int pos){return (pos-1)/bsize+1;}
  34. void dfs(int u,int fa){
  35. st[u]=++e_clk,idfn[e_clk]=u;
  36. for(int i=1;i<=16;i++)f[u][i]=f[f[u][i-1]][i-1];
  37. for(auto v:G[u]){
  38. if(v==fa)continue;
  39. dep[v]=dep[u]+1,f[v][0]=u;
  40. dfs(v,u);
  41. }
  42. ed[u]=++e_clk,idfn[e_clk]=u;
  43. }
  44. int getlca(int x,int y){
  45. if(dep[x]<dep[y])swap(x,y);
  46. for(int i=16;~i;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
  47. if(x==y)return x;
  48. for(int i=16;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
  49. return f[x][0];
  50. }
  51. void read_and_parse(){
  52. n=read(),m=read(),bsize=sqrt(2*n);
  53. for(int i=1;i<=n;i++)a[i]=d[i]=read();
  54. sort(d+1,d+n+1);
  55. tot=unique(d+1,d+n+1)-d-1;
  56. for(int i=1;i<=n;i++)a[i]=lower_bound(d+1,d+tot+1,a[i])-d;
  57. for(int i=1,x,y;i<n;i++){
  58. x=read(),y=read();
  59. G[x].pb(y),G[y].pb(x);
  60. }
  61. dep[1]=1,dfs(1,0);
  62. for(int i=1,x,y;i<=m;i++){
  63. x=read(),y=read();
  64. if(st[x]>st[y])swap(x,y);
  65. int lca=getlca(x,y);
  66. q[i].id=i;
  67. if(lca==x)q[i].l=st[x],q[i].r=st[y],q[i].bl=get(q[i].l);
  68. else q[i].l=ed[x],q[i].r=st[y],q[i].lca=lca,q[i].bl=get(q[i].l);
  69. }
  70. sort(q+1,q+m+1,cmp);
  71. }
  72. bool vis[maxn];
  73. int l=1,r=0,now=0,cnt[maxn],ans[maxm];
  74. inline void update(int pos){
  75. int u=idfn[pos];
  76. if(vis[u]){
  77. --cnt[a[u]];
  78. if(!cnt[a[u]])--now;
  79. }else{
  80. if(!cnt[a[u]])++now;
  81. ++cnt[a[u]];
  82. }
  83. vis[u]^=1;
  84. }
  85. void solve(){
  86. for(int i=1,l=1,r=0;i<=m;i++){
  87. while(r<q[i].r)update(++r);
  88. while(r>q[i].r)update(r--);
  89. while(l<q[i].l)update(l++);
  90. while(l>q[i].l)update(--l);
  91. if(q[i].lca)update(st[q[i].lca]);
  92. ans[q[i].id]=now;
  93. if(q[i].lca)update(st[q[i].lca]);
  94. }
  95. for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
  96. }
  97. int main(){
  98. read_and_parse();
  99. solve();
  100. return 0;
  101. }

【SPOJ10707】COT2 - Count on a tree II的更多相关文章

  1. 【SPOJ10707】 COT2 Count on a tree II

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

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

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

  3. 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 ...

  4. 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  ...

  5. 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 ...

  6. SPOJ10707 COT2 - Count on a tree II 【树上莫队】

    题目分析: 考虑欧拉序,这里的欧拉序与ETT欧拉序的定义相同而与倍增LCA不同.然后不妨对于询问$u$与$v$让$dfsin[u] \leq dfsin[v]$,这样对于u和v不在一条路径上,它们可以 ...

  7. 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)

    http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...

  8. SPOJ COT2 Count on a tree II(树上莫队)

    题目链接:http://www.spoj.com/problems/COT2/ You are given a tree with N nodes.The tree nodes are numbere ...

  9. SPOJ COT2 Count on a tree II (树上莫队)

    题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...

随机推荐

  1. 将选中项的value值赋给select的title

    $('select').change(function () { $(this).attr("title",$(this).find("option:selected&q ...

  2. python爬虫-1

    import resquests #import urllib.request from bs4 import BeautifulSoup from collections import Ordere ...

  3. 从 Aliyun 经典网络迁移到 Aliyun VPC 网络

    由于阿里云策略问题,要求用户从经典网络中全部迁出,搬迁到他们设置的 VPC 网络中.这里的 VPC 大概指的是逻辑上的一个虚拟局域网.即使是实际上你的机器垮机房在阿里云的不同机房.但是他们仍然能从逻辑 ...

  4. DAY06、元组、字典、集合

    一.元组 1.定义:参数为for可以循环的对象 t1 = (1, 2)     t2 = tuple((1, 2))     t3 = (1, )        #定义一个只有一个值的元组 2.常用操 ...

  5. 生成统计数据并导出Excel

    需求:看如下表格的统计需求 生产调度中心部门需要从IT技术部门得到这些统计数据 步骤: (1)获取所有的子公司列表 (2)遍历所有的子公司,获取每个子公司的库存信息 (3)遍历所有的库存信息,并对库存 ...

  6. mysql 数据库的主从同步

    1.复制准备 操作系统 centOS 主库(mysql master):  ip为123.56.94.1   port为3306  mysql 版本 5.7.16 从库(mysql slave):   ...

  7. java中的缓冲流!

    package cn.zhozuohou; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; impor ...

  8. Python包的相对导入时出现问题解决

    资料参考: https://www.cnblogs.com/ArsenalfanInECNU/p/5346751.html 在python导入包,如下: from .units import * 经常 ...

  9. Lodop获取客户端主网卡ip地址是0.0.0.0

    LODOP技术手册的GET_SYSTEM_INFO篇,LODOP可以用语句获取到客户端很多信息,NetworkAdapter.1.IPAddress是主网卡IP地址,通常情况下是没问题的,不过如果当前 ...

  10. Web API 2 添加Models and Controllers Part 2.

    在方案中找到Models文件夹,右键添加类,命名为Author. Author.cs 替换以下代码 C# using System.Collections.Generic; using System. ...