SPOJ10707 COT2-Count on a tree II
COT2 - Count on a tree II
中文题意
离线询问一颗树上路径(u,v)中经过所有点的权值的种类数。
题解
树上莫队。即在树的欧拉序列上进行莫队。同一个点加第一次时增加,第二次时减去增加的影响。
错误记录
用了tarjan LCA,并偷懒将询问和莫队都用一个node表示。意味着每一个询问都要开两个node,写莫队排序sort的时候注意结构体数组长度!莫队排序后两个相同的node不一定相邻,因为可能出现node[i].l/size和node[j].l/size相等,但是node[i].l和node[j].l并不相等的情况。卡了半天。
题目信息不全,权值据说是1e9,别忘了离散化
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <cmath>
void swap(int &a, int &b){int tmp = a;a = b, b = tmp;}
int max(int a, int b){return a > b ? a : b;}
int min(int a, int b){return a < b ? a : b;}
void read(int &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9') c = ch, ch = getchar();
while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = 1000000;
const int MAXM = 1000000;
struct Edge
{
int u, v, nxt;
Edge(int _u, int _v, int _nxt){u = _u, v = _v, nxt = _nxt;}
Edge(){}
}edge[MAXN << 1];
int head[MAXN], cnt;
void insert(int a, int b)
{
edge[++ cnt] = Edge(a, b, head[a]), head[a] = cnt;
edge[++ cnt] = Edge(b, a, head[b]), head[b] = cnt;
}
int tong[MAXN], val[MAXN], num[MAXN], id[MAXN];
int fa[MAXN], seq[MAXN], st[MAXN], et[MAXN], t, sum;
int n, m;
void dfs(int x)
{
seq[++ t] = x;
st[x] = t;
for(int pos = head[x];pos;pos = edge[pos].nxt)
{
int v = edge[pos].v;
if(v == fa[x]) continue;
fa[v] = x;
dfs(v);
}
seq[++ t] = x;
et[x] = t;
}
int cmp(int a, int b)
{
return val[a] < val[b];
}
struct Node
{
int l, r, id, lca, nxt, u, v, need_lca;
Node(int _u, int _v, int _id, int _nxt){u = _u, v = _v, id = _id, nxt = _nxt;}
Node(){}
void init()
{
if(lca == u)
l = st[lca], r = st[v], need_lca = 0;
else if(lca == v)
l = st[lca], r = st[u], need_lca = 0;
else
{
if(st[u] < st[v]) l = et[u], r = st[v];
else l = et[v], r = st[u];
need_lca = 1;
}
return ;
}
}node[MAXM];
int head_node[MAXM], cnt_node = 1;
void insert_node(int u, int v, int id)
{
node[++ cnt_node] = Node(u, v, id, head_node[u]), head_node[u] = cnt_node;
node[++ cnt_node] = Node(v, u, id, head_node[v]), head_node[v] = cnt_node;
}
int ans[MAXM];
int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int vis[MAXN];
void dfs_tarjan(int x)
{
vis[x] = 1;
for(int pos = head[x];pos;pos = edge[pos].nxt)
{
int v = edge[pos].v;
if(vis[v]) continue;
dfs_tarjan(v);
int f1 = find(x), f2 = find(v);
fa[f2] = f1;
}
for(int pos = head_node[x];pos;pos = node[pos].nxt)
{
int v = node[pos].v;
if(vis[v])
node[pos].lca = node[pos ^ 1].lca = find(v);
}
}
void tarjan_lca()
{
for(int i = 1;i <= n;++ i) fa[i] = i;
dfs_tarjan(1);
}
int size;
int cmp2(Node& a, Node& b)
{
return a.l/size == b.l/size ? a.r < b.r : a.l/size < b.l/size;
}
int w[MAXN];
void add(int x)
{
if(w[x] == 0) tong[val[x]] += 1;
else if(w[x] == 1) tong[val[x]] -= 1;
if(tong[val[x]] == 1 && w[x] == 0) ++ sum;
if(tong[val[x]] == 0 && w[x] == 1) -- sum;
++ w[x];
}
void del(int x)
{
if(w[x] == 1) tong[val[x]] -= 1;
else if(w[x] == 2) tong[val[x]] += 1;
if(tong[val[x]] == 1 && w[x] == 2) ++ sum;
if(tong[val[x]] == 0 && w[x] == 1) -- sum;
-- w[x];
}
bool is_cal[MAXM << 1];
int main()
{
read(n), read(m);
for(int i = 1;i <= n;++ i) read(val[i]), id[i] = i;
for(int i = 1;i < n;++ i)
{
int tmp1, tmp2;
read(tmp1), read(tmp2);
insert(tmp1, tmp2);
}
std::sort(id + 1, id + 1 + n, cmp);
for(int i = 1, j = 1;i <= n;)
{
num[j] = val[id[i]];
while(val[id[i]] == num[j]) val[id[i]] = j, ++ i;
++ j;
}
dfs(1);
for(int i = 1;i <= m;++ i)
{
int tmp1, tmp2;
read(tmp1), read(tmp2);
insert_node(tmp1, tmp2, i);
}
tarjan_lca();
for(int i = 2;i <= cnt_node;++ i)
node[i].init();
size = sqrt(n);
if(size == 0) size = 1;
std::sort(node + 2, node + 1 + cnt_node, cmp2);
int l = 1, r = 1;
add(seq[1]);
for(int i = 2;i <= cnt_node;++ i)
{
if(is_cal[node[i].id]) continue;
is_cal[node[i].id] = 1;
while(l < node[i].l) del(seq[l]), ++ l;
while(l > node[i].l) -- l, add(seq[l]);
while(r < node[i].r) ++ r, add(seq[r]);
while(r > node[i].r) del(seq[r]), -- r;
if(node[i].need_lca) add(node[i].lca);
ans[node[i].id] = sum;
if(node[i].need_lca) del(node[i].lca);
}
for(int i = 1;i <= m;++ i)
printf("%d\n", ans[i]);
return 0;
}
SPOJ10707 COT2-Count on a tree II的更多相关文章
- SPOJ10707 COT2 - Count on a tree II 【树上莫队】
题目分析: 考虑欧拉序,这里的欧拉序与ETT欧拉序的定义相同而与倍增LCA不同.然后不妨对于询问$u$与$v$让$dfsin[u] \leq dfsin[v]$,这样对于u和v不在一条路径上,它们可以 ...
- 【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 ...
- 「SPOJ10707」Count on a tree II
「SPOJ10707」Count on a tree II 传送门 树上莫队板子题. 锻炼基础,没什么好说的. 参考代码: #include <algorithm> #include &l ...
- 【SPOJ10707】COT2 - Count on a tree II
题目大意:给定一棵 N 个节点的无根树,每个节点有一个颜色.现有 M 个询问,每次询问一条树链上的不同颜色数. 题解:学会了树上莫队. 树上莫队是将节点按照欧拉序进行排序,将树上问题转化成序列上的问题 ...
- 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 ...
- SPOJ COT2 Count on a tree II (树上莫队)
题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...
- [SP10707]COT2 - Count on a tree II
题目大意:有一棵$n$个节点的树,第$i$个点有一个颜色$C_i$,$m$组询问,每次问$x->y$的路径上有多少种颜色 题解:树上莫队,把树按欧拉序展开成一条链,令第$i$个节点第一次出现在序 ...
随机推荐
- Photon Server的服务器端配置
Photon Server与Unity3D的交互分为3篇博文实现 (1)Photon Server的服务器端配置 (2)Photon Server的Unity3D客户端配置 (3)Photon Ser ...
- ACM-ICPC 2018 沈阳赛区网络预赛-B,F,G
学长写的 F. Fantastic Graph "Oh, There is a bipartite graph.""Make it Fantastic." X ...
- iOS开发静态库冲突——如何查看静态库(.O)中方法名
1.bug产生 应用第三方静态库之后提示冲突错误: 2.bug分析 一般会提示哪两个库冲突: CameraShowGLView.o是自己创建的类编译生成的: libLechangeSDK.a是添加的静 ...
- HDU 2586 /// tarjan离线求树上两点的LCA
题目大意: 询问一棵树里 u 到 v 的距离 可由 dis[ u到根 ] + dis[ v到根 ] - 2*dis[ lca(u,v) ] 得到 https://blog.csdn.net/csyzc ...
- 【POJ】1321棋盘问题
题目链接:http://poj.org/problem?id=1321 题意:见题干,很清楚了. 题解:简单dfs,参照八皇后 代码: #include<iostream> #includ ...
- Caused by: java.io.FileNotFoundException: class path resource [com/cxy/springboot/mapping/] cannot be resolved to URL because it does not exist
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.conte ...
- D3.js坐标轴的绘制方法、添加坐标轴的刻度和各比例尺的坐标轴(V3版本)
坐标轴(Axis) 坐标轴(Axis)在很多图表中都可见到,例如柱形图.折线图.散点图等.坐标轴由一组线段和文字组成,坐标轴上的点由一个坐标值确定.但是,如果使用SVG的直线和文字一笔一画的绘制坐 ...
- mysql连接超时的问题处理
1. 内网 ts 连接mysql 有时候会连接失败, 原因是 连接超时, 当时所有服务器一起启动,抢占资源,导致连接超过10s. 现在增加一次连接机会, 增加一些日志. 2. 并且对mysql 全局参 ...
- 从零开始:Mysql基于Amoeba的集群搭建
从零开始:Mysql基于Amoeba的集群搭建 准备环境 1.mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz 2.amoeba-mysql-binary-2.0. ...
- CSIC_716_20191112【闭包函数和装饰器】
闭包函数 什么是闭包函数:闭包函数是函数嵌套.函数对象.名称空间和作用域的集合体. 闭包函数必须在函数内部定义,闭包函数可以引用外层函数的名字. # _*_ coding: gbk _*_ # @Au ...