[SP10707]COT2 - Count on a tree II
题目大意:有一棵$n$个节点的树,第$i$个点有一个颜色$C_i$,$m$组询问,每次问$x->y$的路径上有多少种颜色
题解:树上莫队,把树按欧拉序展开成一条链,令第$i$个节点第一次出现在序列中为$in_i$,第二次为$out_i$,每一个询问就是看$in_x->in_y$中只出现一次的节点的颜色,但发现如果$x$不为$x,y$的$lca$的话$lca$不会被计入答案,特判一下就行
卡点:1$\sim$2.数组未开大
3.$tarjan$求$lca$时加询问加错
4.为先加入第一个点导致答案多一
C++ Code:
#include <cstdio>
#include <algorithm>
#define maxn 40010
#define maxm 100010
#define N (maxn << 1)
#define bl(x) ((x) >> 9)
int n, m;
int in[maxn], out[maxn], date[N], idx;
struct Query {
int l, r, lca, id;
bool addlca;
inline bool operator < (const Query &rhs) const {
return (bl(l) == bl(rhs.l)) ? r < rhs.r : l < rhs.l;
}
} q[maxm];
namespace tree {
int head[maxn], cnt = 0;
struct Edge {
int to, nxt;
} e[maxn << 1];
inline void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
}
int fa[maxn]; void dfs(int u) {
date[in[u] = ++idx] = u;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u]) {
fa[v] = u;
dfs(v);
}
}
date[out[u] = ++idx] = u;
}
}
namespace tarjan {
int head[maxn], cnt = 0;
struct QUERY {
int v, nxt, id;
} Q[maxm << 1];
inline void add(int a, int b, int c) {
Q[++cnt] = (QUERY) {b, head[a], c}; head[a] = cnt;
Q[++cnt] = (QUERY) {a, head[b], c}; head[b] = cnt;
} int f[maxn];
inline void init(int n) {
for (int i = 1; i <= n; i++) f[i] = i;
}
int find(int x) {return (x == f[x] ? x : (f[x] = find(f[x])));} bool vis[maxn];
void dfs(int u) {
for (int i = tree::head[u]; i; i = tree::e[i].nxt) {
int v = tree::e[i].to;
if (v != tree::fa[u]) {
dfs(v);
f[v] = u;
}
}
for (int i = tarjan::head[u]; i; i = tarjan::Q[i].nxt) q[Q[i].id].lca = find(Q[i].v);
}
}
#define ONLINE_JUDGE
#include <cctype>
namespace R {
int x;
#ifdef ONLINE_JUDGE
char *ch, op[1 << 26];
inline void init() {
fread(ch = op, 1, 1 << 26, stdin);
}
inline int read() {
while (isspace(*ch)) ch++;
for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15);
return x;
}
#else
char ch;
inline int read() {
ch = getchar();
while (isspace(ch)) ch = getchar();
for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
return x;
}
#endif
} inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
int num[maxn], W[maxn], w[maxn], ans[maxm];
bool vis[maxn];
int main() {
#ifdef ONLINE_JUDGE
R::init();
#endif
tarjan::init(n = R::read()); m = R::read();
for (int i = 1; i <= n; i++) W[i] = w[i] = R::read();
int tot = (std::sort(W + 1, W + n + 1), std::unique(W + 1, W + n + 1) - W - 1);
for (int i = 1; i <= n; i++) w[i] = std::lower_bound(W + 1, W + tot + 1, w[i]) - W;
for (int i = 1; i < n; i++) tree::add(R::read(), R::read());
tree::dfs(1);
for (int i = 1; i <= m; i++) tarjan::add(q[i].l = R::read(), q[i].r = R::read(), q[i].id = i);
tarjan::dfs(1);
for (int i = 1; i <= m; i++) {
int &l = q[i].l, &r = q[i].r;
if (in[l] > in[r]) swap(l, r);
l = (q[i].addlca = (q[i].lca != l)) ? out[l] : in[l];
r = in[r];
}
std::sort(q + 1, q + m + 1);
int l, r, res; l = 1, r = 1, res = 1;
vis[date[1]] = 1; num[w[date[1]]]++;
for (int i = 1; i <= m; i++) {
while (l > q[i].l) (vis[date[--l]] ^= 1) ? (res += num[w[date[l]]]++ == 0) : (res -= --num[w[date[l]]] == 0);
while (r < q[i].r) (vis[date[++r]] ^= 1) ? (res += num[w[date[r]]]++ == 0) : (res -= --num[w[date[r]]] == 0);
while (l < q[i].l) (vis[date[l]] ^= 1) ? (res += num[w[date[l++]]]++ == 0) : (res -= --num[w[date[l++]]] == 0);
while (r > q[i].r) (vis[date[r]] ^= 1) ? (res += num[w[date[r--]]]++ == 0) : (res -= --num[w[date[r--]]] == 0);
ans[q[i].id] = res + (q[i].addlca && !num[w[q[i].lca]]);
}
for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);
return 0;
}
[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 莫队上树
题意:求一条链 \((u,v)\) 上不同的颜色数. 我们可以求出树的出栈入栈序(or 括号序?我也不确定). 图(from attack) 然后有一个很优美的性质: 设点 \(u\) 的入栈时间为 ...
- SP10707 COT2 - Count on a tree II [树上莫队学习笔记]
树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...
- 【SPOJ10707】 COT2 Count on a tree II
SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...
- 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 ...
- 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 ...
- 【树上莫队】【SP10707】 COT2 - Count on a tree II
Description 给定一棵 \(n\) 个点的树,每个节点有一个权值,\(m\) 次询问,每次查询两点间路径上有多少不同的权值 Input 第一行是 \(n\) 和 \(m\) 第二行是 \(n ...
随机推荐
- UISearchController(使用)
效果图1 效果图2 其实一般是在第一种情况使用的UISearchController,但是第二种情况这种又懒得去用uisearchbar+uitableview等等去处理, 其实主要是对数据源的合理使 ...
- 【学时总结】◆学时·VIII◆ 树形DP
◆学时·VIII◆ 树形DP DP像猴子一样爬上了树……QwQ ◇ 算法概述 基于树的模型,由于树上没有环,满足DP的无后效性,可以充分发挥其强大统计以及计算答案的能力. 一般来说树形DP的状态定义有 ...
- Java中堆、栈,静态方法和非静态方法的速度问题
一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储 ...
- 详解MessageBox(),MsgBox函数的正确使用
//或者使用chr(13),chr(10)效果一样 MsgBox "a"&chr(13)&"b"&chr(10)&"c ...
- 无序数组中第K大的数
1. 排序法 时间复杂度 O(nlogn) 2. 使用一个大小为K的数组arr保存前K个最大的元素 遍历原数组,遇到大于arr最小值的元素时候,使用插入排序方法,插入这个元素 时间复杂度,遍历是 O( ...
- 笔记-scrapy-setting
笔记-scrapy-setting 1. 简介 Scrapy设置允许您自定义所有Scrapy组件的行为,包括核心,扩展,管道和蜘蛛本身. 可以使用不同的机制来填充设置,每种机制都有不同的优先级 ...
- TouTiao开源项目 分析笔记20 问答详情
1.效果预览 1.1.效果预览,从问答列表开始 前面实现了从列表到内容. 这里主要讲解从内容到详情. 点击每一个回答内容,进入回答详情页面. 1.2.触发的点击事件 在WendaContentView ...
- P1182 数列分段Section II
P1182 数列分段Section II 题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 ...
- border与透明边框
1.背景:怎样增加复选框响应域的大小?就是,复选框点击区域增大一些 需求复选框的视觉区域大小(不含边框)是16px*16px 现在要把可点击区域增加到20px*20px 解决方案: box-shado ...
- 考拉Android统一弹框
作者:钱成杰 背景 在快速开发的背景下,经历了n个版本后的考拉Android App中已经存在了各种各样看似相同却各有差别的弹框样式.其中包括系统弹框和自定义弹框,并且在线上时常会出现IllegalA ...