SP10707 COT2 - Count on a tree II 莫队上树
题意:求一条链 \((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\) 的颜色。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=200010,M=200010; bool vis[N];
int n,m,B,cnt,num,mem[N<<1],pos[N<<1],a[N],b[N],c[N],ans[N],tot;
int vr[N<<1],nxt[N<<1],fir[N],dfn[N],low[N],pre[N],top[N],sz[N],son[N],d[N];
inline void add(int u,int v) {
vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;
vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt;
}
inline void dfs(int u) { sz[u]=1,dfn[u]=++num,mem[num]=u;
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(d[v]) continue; pre[v]=u,d[v]=d[u]+1,dfs(v);
if(sz[son[u]]<sz[v]) son[u]=v; sz[u]+=sz[v];
} low[u]=++num,mem[num]=u;
}
inline void dfs2(int u,int tp) { top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(v!=son[u]&&v!=pre[u]) dfs2(v,v);
}
}
inline int lca(int u,int v) {
for(;top[u]!=top[v];u=pre[top[u]]) if(d[top[u]]<d[top[v]]) swap(u,v);
return d[u]<d[v]?u:v;
}
struct node {int l,r,op,id;
inline bool operator < (const node& that) const
{return pos[l]==pos[that.l]?(pos[l]&1)?r<that.r:r>that.r:l<that.l;}
}q[M];
inline void add(int x) {if(++c[x]==1) ++tot;}
inline void sub(int x) {if(--c[x]==0) --tot;}
inline void f(int u) {vis[u]?sub(a[u]):add(a[u]); vis[u]^=1;}
inline void main() {
n=g(),m=g(); B=sqrt(n);
for(R i=1;i<=n;++i) a[i]=g();
memcpy(b,a,sizeof b);
sort(b+1,b+n+1); R t=unique(b+1,b+n+1)-b-1;
for(R i=1;i<=n;++i) a[i]=lower_bound(b+1,b+t+1,a[i])-b;
for(R i=1,u,v;i<n;++i) u=g(),v=g(),add(u,v); d[1]=1,dfs(1),dfs2(1,1);
for(R i=1,u,v,l;i<=m;++i) {
u=g(),v=g(),l=lca(u,v);
if(dfn[u]>dfn[v]) swap(u,v);
if(l==u) q[i]=(node){dfn[u],dfn[v],0,i};
else q[i]=(node){low[u],dfn[v],l,i};
} for(R i=1;i<=2*n;++i) pos[i]=(i-1)/B+1;
sort(q+1,q+m+1);
for(R i=1,l=1,r=0,op,LL,RR,id;i<=m;++i) {
LL=q[i].l,RR=q[i].r,op=q[i].op,id=q[i].id;
while(l<LL) f(mem[l++]);
while(l>LL) f(mem[--l]);
while(r<RR) f(mem[++r]);
while(r>RR) f(mem[r--]);
ans[id]=tot+(op&&c[a[op]]==0);
} for(R i=1;i<=m;++i) printf("%d\n",ans[i]);
}
} signed main() {Luitaryi::main(); return 0;}
2019.11.21
SP10707 COT2 - Count on a tree II 莫队上树的更多相关文章
- SP10707 COT2 - Count on a tree II 莫队
链接 https://vjudge.net/problem/SPOJ-COT2 https://www.luogu.org/problemnew/show/SP10707 思路 dfs欧拉序转化为普通 ...
- SP10707 COT2 - Count on a tree II (树上莫队)
大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...
- SP10707 COT2 - Count on a tree II [树上莫队学习笔记]
树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...
- [SP10707]COT2 - Count on a tree II
题目大意:有一棵$n$个节点的树,第$i$个点有一个颜色$C_i$,$m$组询问,每次问$x->y$的路径上有多少种颜色 题解:树上莫队,把树按欧拉序展开成一条链,令第$i$个节点第一次出现在序 ...
- 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 ...
- 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 ...
- 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 ...
- 【SPOJ10707】 COT2 Count on a tree II
SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...
- 【树上莫队】【SP10707】 COT2 - Count on a tree II
Description 给定一棵 \(n\) 个点的树,每个节点有一个权值,\(m\) 次询问,每次查询两点间路径上有多少不同的权值 Input 第一行是 \(n\) 和 \(m\) 第二行是 \(n ...
随机推荐
- C++ 读取 MATLAB 的 .m 文件,并发送到 MATLAB 运行
本代码是由「Microsoft Visual Studio 2015 Enterprise」编写. 想要了解更多 C++ 与 MATLAB 混合编程的知识,可以参考我的另一篇博客:C++ 与 MATL ...
- IP核——FIFO
一.Quartus 1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager 2.弹出创建页面,选择Creat a new custom megafunc ...
- Codeforces Round #568 Div. 2
没有找到这场div3被改成div2的理由. A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long ...
- 全栈项目|小书架|服务器开发-Koa2中间件机制洋葱模型了解一下
KOA2 是什么? Koa是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 通过利用 asyn ...
- Python与Golang协程异同
背景知识 这里先给出一些常用的知识点简要说明,以便理解后面的文章内容. 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定 ...
- Html form表单大全(一)
在前后端交互的过程中,除了ajax请求之外,最常见的就是表单请求了. 由于form表单属性多,表单标签内容多且复杂,不深究的话很难全面的弄明白. 接下来就来详细的说一说整个form表单都有些什么,并且 ...
- js 的七大原则--单一原则、开闭原则、替换原则(一)
一.前言: js 的七大设计原则: 1.单一原则 2.开闭原则 3.里氏替换原则 4.依赖倒转原则 5.接口隔离原则 6.合成复用原则 7.迪米尔法则 二.单一原则 1.定义:单一原则就是一个对象或者 ...
- React Native 开发豆瓣评分(五)屏幕适配方案
前言 React Native 是以实际像素 dp 为单位的,这导致在不同分辨率的屏幕会有不一样的显示情况. 在原生 Android 中,可以根据不同的分辨率添加不同的样式目录,以解决不同分辨率的问题 ...
- javascript_18-Array 数组
数组 数组-引用类型,JavaScript中的内置对象 Array对象的属性 length 获取数组的长度(元素个数) 检测数组 instanceof Array.isArray() //h5新增 常 ...
- 使用终端批量下载 B 站视频
需要使用一个叫做 you-get 的命令行程序 可以通过 Homebrew 安装(macOS), 安装命令为 brew install you-get, 其他平台的安装可参考 Github 主页: s ...