传送门

题意:

给你一棵大小为$n$的树,每个点都有点权。现在有$m$个询问,每个询问给你一个两个数$a,b$,问你从点$a$到点$b$之间的路径中不同的点权的个数。

分析:

万恶的spoj并没有写点权的数据范围,害我我先re(此题需要离散化点权)

求解带有询问的不同数的个数这类题,~~一看就相当莫队~~ ,但是因为莫队只能够在一个序列上进行操作,因此我们考虑如何让树的树形结构转化为线性的结构。

我们考虑使用树的欧拉序。

我们设$st[]$为第一次遍历经过的编号,$en[]$为回溯时经过的编号,则现在有两种方案:

1. 如果两个节点$a,b$在同一条链上,则我们直接选取欧拉序区间$([st[a],st[b])$
2. 如果两个结点不在同一条链上,则我们直接选取欧拉序区间$(en[a],st[b])$

对于每个区间,我们只需要统计该区间中,数字只出现一次的数字的个数。

与此同时,因为在操作$2$中,两个节点的最近公共祖先是没有被贡献的,因此我们还得加上$LCA(a,b)$的贡献。

之后就是我们普通莫队的分块了。

#include <bits/stdc++.h>
#define maxn 200005
#define K 20
using namespace std;
struct P{int l,r,z,id;
}Q[maxn];
struct Node{int to,next;
}q[maxn<<1];
int lim,Cnt,pos[maxn<<1],c[maxn];
int n,m,loc[maxn<<1],dfn,st[maxn],en[maxn],d[maxn],f[maxn][25];
int ans[maxn],cnt[maxn],sum,head[maxn];
bool vis[maxn];
bool cmp(const P&a,const P&b){return pos[a.l]==pos[b.l]?a.r<b.r:pos[a.l]<pos[b.l];
}
void add_edge(int from,int to){q[Cnt].to=to;q[Cnt].next=head[from];head[from]=Cnt++;
}
void dfs(int x){loc[st[x]=++dfn]=x;vis[x]=1;for(int i=1;i<=K;i++) f[x][i]=f[f[x][i-1]][i-1];for(int i=head[x];i!=-1;i=q[i].next){int to=q[i].to;if(!vis[to]) d[to]=d[f[to][0]=x]+1,dfs(to);}loc[en[x]=++dfn]=x;
}
int lca(int x,int y){if(x==y)return x;if(d[x]<d[y])swap(x,y);for(int i=K;~i;i--) if(d[f[x][i]]>=d[y])x=f[x][i];if(x==y) return x;for(int i=K;~i;i--){if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];}return f[x][0];
}
void deal(int x){if(!vis[x]){if(!(--cnt[c[x]])) sum--;}else if(!(cnt[c[x]]++)) sum++;vis[x]^=1;
}
int D[maxn];
int main()
{scanf("%d%d",&n,&m);memset(head,-1,sizeof(head));Cnt=0;for(int i=1;i<=n;i++){scanf("%d",&c[i]);D[i]=c[i];}sort(D+1,D+1+n);for(int i=1;i<=n;i++) c[i]=lower_bound(D+1,D+1+n,c[i])-D;for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);add_edge(x,y),add_edge(y,x);}dfs(d[1]=1),lim=(int)sqrt(n*2+0.5);for(int i=1;i<=dfn;i++) pos[i]=(i-1)/lim+1;for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);Q[i].id=i;if(st[x]>st[y]) swap(x,y);int z=lca(x,y);if(z==x) Q[i].l=st[x],Q[i].r=st[y];else Q[i].l=en[x],Q[i].r=st[y],Q[i].z=z;}sort(Q+1,Q+1+m,cmp);int l=1,r=0;for(int i=1;i<=m;i++){while(r<Q[i].r) deal(loc[++r]);while(r>Q[i].r) deal(loc[r--]);while(l<Q[i].l) deal(loc[l++]);while(l>Q[i].l) deal(loc[--l]);if(Q[i].z) deal(Q[i].z);ans[Q[i].id]=sum;if(Q[i].z) deal(Q[i].z);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}

转载于:https://www.cnblogs.com/Chen-Jr/p/11007138.html

SPOJ COT2 (树上莫队)相关推荐

  1. 【SPOJ COT2】Count on a tree II,树上莫队

    Time:2016.09.07 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 第一次写树上莫队 被char哥怒裱一通 实际上还是比较简单的 序列的相关维护问题转移到树上一般都要涉及 ...

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

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

  3. 莫队算法二(树上莫队cot2,Haruna’s Breakfast)

    例一:不带修改 Count on a tree II Time Limit: 1207MS   Memory Limit: 1572864KB   64bit IO Format: %lld & ...

  4. [学习笔记]树上莫队

    其实树上莫队是一个欧拉序而已嘛,像普通的莫队,特判一下出现过两次的值就行了 设 \(st_i\) 为 \(i\) 进栈的时间,\(ed_i\) 为 \(i\) 出栈的时间,\(dfn_x<dfn ...

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

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

  6. 莫队算法 (普通莫队、带修莫队、树上莫队)

    莫队算法 主要基于分块的思想 用结构体记录询问的左右端点及询问编号 (这是一个离线算法) 通过排序优化指针扫描顺序优化时间复杂度 . 1.普通莫队 例题:SP3267 DQUERY - D-query ...

  7. 莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】

    一.理解 我的理解就是巧妙的暴力,利用双指针以及分块思想,巧妙的移动双指针,时间复杂度可以达到O(NlogN). 强推博客:写的又好又全.链接 二.套路 1.普通莫队 [1]核心代码 bool cmp ...

  8. LG P4074 [WC2013] 糖果公园(带修莫队,树上莫队)

    LG P4074 [WC2013] 糖果公园 Solution 树上带修莫队,主要还是复习带修莫队和树上莫队. 带修莫队: 带修莫队要先对lll分块的序号作为第一关键字,对rrr分块的序号作为第二关键 ...

  9. YBTOJ洛谷P4074:糖果公园(树上莫队)

    文章目录 解析 update: 代码 所谓树上莫队,就是在树上的莫队 (逃) 传送门 解析 似乎就是树上的这道题 考虑如何转化为序列问题呢? 考虑dfs序 但是又一个问题... 似乎这条链的dfs序不 ...

  10. jzoj3360-[NOI2013模拟]苹果树【树上莫队,LCA】

    正题 题目大意 一棵树上每个节点有不同的颜色,然后每次询问(x,y,a,b)(x,y,a,b)(x,y,a,b)表示将颜色aaa看为颜色bbb的情况下询问xxx到yyy有多少不种的颜色. 解题思路 数 ...

最新文章

  1. jar包升级部署到服务器详细流程,将服务部署在linux中
  2. eclipse 将javaWeb项目转化成maven项目
  3. [SQL] 外卖系统数据库设计
  4. Adobe的学者约翰—沃洛克博士
  5. C# 操作http协议学习总结
  6. Codeforces Round #703 (Div. 2) D . Max Median 二分 +思维
  7. 多生产者-多消费者问题
  8. 浏览器关闭 session并不会被干掉
  9. grub的概念,简单描述一下
  10. p71_文件传送协议FTP
  11. socket.io 消息发送
  12. hive split 注意事项
  13. Tomcat内存溢出(OutOfMemoryError)
  14. 软件工程 | 第三章 需求分析
  15. 00套经典机械结构设计非标自动化SW机构3D图纸solidWorks模型库
  16. TA_Lib库指标中文说明
  17. 计算机基础技能培养,计算机基础技能培养大纲(非计算机专业).doc
  18. Blender2.9基础二:UV篇
  19. 如何解决:微云下载文件总是下载失败
  20. Python数据导入

热门文章

  1. python循环结构高一信息技术有限公司_Python之循环结构
  2. python给用户打标签_用Python实现RFM模型——互联网产品用户分层必备技巧
  3. php 匹配括号的个数,php 正则匹配括号内容 PHP实现正则匹配所有括号中的内容
  4. ASCII码从小到大排序(字典序)
  5. linux 项目内存吃掉,Linux内存被吃掉了,它去哪里了?
  6. pillow模块 (PIL) 生成验证码
  7. 如何快速掌握man手册的使用
  8. Java初级笔记-第一章
  9. Zabbix agent 在windows上安装部署
  10. 图片加载库Glide