SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)
COT2 - Count on a tree II
You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.
We will ask you to perform the following operation:
- u v : ask for how many different integers that represent the weight of nodes there are on the path from u to v.
Input
In the first line there are two integers N and M. (N <= 40000, M <= 100000)
In the second line there are N integers. The i-th integer denotes the weight of the i-th node.
In the next N-1 lines, each line contains two integers u v, which describes an edge (u, v).
In the next M lines, each line contains two integers u v, which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.
Output
For each operation, print its result.
Example
- Input:
- 8 2
- 105 2 9 3 8 5 7 7
- 1 2
- 1 3
- 1 4
- 3 5
- 3 6
- 3 7
- 4 8
- 2 5
- 7 8
- Output:
- 4
- 4
题目链接:SPOJ COT2
一开始不太会,看着这个人的教程写的:树上莫队,然而还是有几个地方不是很懂而且他的简洁代码跟文中的一些变量名对不上号……,但至少没百度搜到的某些题解代码写的丑
他的主要做法就是把树用稍微修改的DFS序变成序列,然后根据两种不同的情况进行判断,并且过程中要算上LCA的贡献,代码虽然写出来了但是感觉跟文中的方法有一点出入,有待理解
最后的LCA判断实际上是多出来的一个点,要还原回去,否则指针是在区间移动的只管辖区间,这个多出来的点会造成错误的影响
代码:
- #include <stdio.h>
- #include <bits/stdc++.h>
- using namespace std;
- #define INF 0x3f3f3f3f
- #define LC(x) (x<<1)
- #define RC(x) ((x<<1)+1)
- #define MID(x,y) ((x+y)>>1)
- #define CLR(arr,val) memset(arr,val,sizeof(arr))
- #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
- typedef pair<int, int> pii;
- typedef long long LL;
- const double PI = acos(-1.0);
- const int N = 40010;
- const int M = 200010;
- struct edge
- {
- int to, nxt;
- edge() {}
- edge(int _to, int _nxt): to(_to), nxt(_nxt) {}
- };
- struct query
- {
- int u, v;
- int lca, x;
- int id, l, r, b;
- bool operator<(const query &rhs)const
- {
- if (b != rhs.b)
- return b < rhs.b;
- return r < rhs.r;
- }
- };
- edge E[N << 1];
- query Q[M];
- int head[N], tot;
- int arr[N];//values in nodes
- int ver[N << 1], F[N], D[N << 1], dp[N << 1][18], ts; //for LCA
- int ST[N << 1], EN[N << 1], A[N << 1], sz, unit; //for Mo's algo
- vector<int>vec;
- int ans[M], cnt[N];
- int cnode[N];
- void init()
- {
- CLR(head, -1);
- tot = 0;
- ts = 0;
- sz = 0;
- vis.reset();
- vec.clear();
- CLR(ans, 0);
- CLR(cnt, 0);
- CLR(cnode, 0);
- }
- inline void add(int s, int t)
- {
- E[tot] = edge(t, head[s]);
- head[s] = tot++;
- }
- void dfs(int u, int pre, int d)
- {
- ver[++ts] = u;
- D[ts] = d;
- F[u] = ts;
- ST[u] = ++sz;
- A[sz] = u;
- for (int i = head[u]; ~i; i = E[i].nxt)
- {
- int v = E[i].to;
- if (v != pre)
- {
- dfs(v, u, d + 1);
- ver[++ts] = u;
- D[ts] = d;
- }
- }
- EN[u] = ++sz;
- A[sz] = u;
- }
- void RMQ_init(int l, int r)
- {
- int i, j;
- for (i = l; i <= r; ++i)
- dp[i][0] = i;
- for (j = 1; l + (1 << j) - 1 <= r; ++j)
- {
- for (i = l; i + (1 << j) - 1 <= r; ++i)
- {
- int a = dp[i][j - 1], b = dp[i + (1 << (j - 1))][j - 1];
- dp[i][j] = D[a] < D[b] ? a : b;
- }
- }
- }
- int LCA(int u, int v)
- {
- int l = F[u], r = F[v];
- if (l > r)
- swap(l, r);
- int k = log2(r - l + 1);
- int a = dp[l][k], b = dp[r - (1 << k) + 1][k];
- return D[a] < D[b] ? ver[a] : ver[b];
- }
- inline void Add(const int &u,int &Ans)
- {
- ++cnode[u];
- if (cnode[u] == 1)
- {
- if (++cnt[arr[u]] == 1)
- ++Ans;
- }
- else if (cnode[u] == 2)
- {
- if (--cnt[arr[u]] == 0)
- --Ans;
- }
- }
- inline void Del(const int &u, int &Ans)
- {
- --cnode[u];
- if (cnode[u] == 0)
- {
- if (--cnt[arr[u]] == 0)
- --Ans;
- }
- else if (cnode[u] == 1)
- {
- if (++cnt[arr[u]] == 1)
- ++Ans;
- }
- }
- int main(void)
- {
- int n, m, i;
- while (~scanf("%d%d", &n, &m))
- {
- init();
- for (i = 1; i <= n; ++i)
- {
- scanf("%d", &arr[i]);
- vec.push_back(arr[i]);
- }
- sort(vec.begin(), vec.end());
- vec.erase(unique(vec.begin(), vec.end()), vec.end());
- for (i = 1; i <= n; ++i)
- arr[i] = lower_bound(vec.begin(), vec.end(), arr[i]) - vec.begin() + 1;
- for (i = 1; i < n; ++i)
- {
- int u, v;
- scanf("%d%d", &u, &v);
- add(u, v);
- add(v, u);
- }
- dfs(1, -1, 0);
- unit = sqrt(sz);
- RMQ_init(1, ts);
- for (i = 0; i < m; ++i)
- {
- scanf("%d%d", &Q[i].u, &Q[i].v);
- Q[i].id = i;
- Q[i].lca = LCA(Q[i].u, Q[i].v);
- if (ST[Q[i].u] > ST[Q[i].v])
- swap(Q[i].u, Q[i].v);
- if (Q[i].lca == Q[i].u)
- {
- Q[i].l = ST[Q[i].u];
- Q[i].r = ST[Q[i].v];
- Q[i].x = 0;
- }
- else
- {
- Q[i].l = EN[Q[i].u];
- Q[i].r = ST[Q[i].v];
- Q[i].x = 1;
- }
- Q[i].b = Q[i].l / unit;
- }
- sort(Q, Q + m);
- int L = Q[0].l, R = L - 1;
- int Ans = 0;
- for (i = 0; i < m; ++i)
- {
- while (L > Q[i].l)
- Add(A[--L], Ans);
- while (L < Q[i].l)
- Del(A[L++], Ans);
- while (R > Q[i].r)
- Del(A[R--], Ans);
- while (R < Q[i].r)
- Add(A[++R], Ans);
- if (Q[i].x)
- Add(Q[i].lca, Ans);
- ans[Q[i].id] = Ans;
- if (Q[i].x)
- Del(Q[i].lca, Ans);
- }
- for (i = 0; i < m; ++i)
- printf("%d\n", ans[i]);
- }
- return 0;
- }
SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)的更多相关文章
- 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)
题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无 ...
- spoj COT2 - Count on a tree II 树上莫队
题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的, 受益匪浅.. #include <iostream> #include < ...
- SPOJ COT2 Count on a tree II 树上莫队算法
题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...
- SPOJ COT2 Count on a tree II (树上莫队)
题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...
- 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 ...
- 【SPOJ10707】 COT2 Count on a tree II
SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...
- 【BZOJ2589】 Spoj 10707 Count on a tree II
BZOJ2589 Spoj 10707 Count on a tree II Solution 吐槽:这道题目简直...丧心病狂 如果没有强制在线不就是树上莫队入门题? 如果加了强制在线怎么做? 考虑 ...
- 【SPOJ】Count On A Tree II(树上莫队)
[SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...
随机推荐
- Problem A: 李白打酒
Problem A: 李白打酒 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 825 Solved: 373[Submit][Status][Web ...
- 2018.2.5 PHP如何写好一个程序用框架
随着PHP标准和Composer包管理工具的面世,普通开发者撸一个框架已经不再是什么难事了. 无论是路由管理.ORM管理.还是视图渲染都有许许多多优秀的包可以使用.我们就像堆积木一样把这些包用comp ...
- 解决mysql8小时无连接自动断掉机制
windows下打开my.ini,增加: interactive_timeout=28800000 wait_timeout=28800000 MySQL是一个小型关系型数据库管理系统,由于MySQL ...
- MySQL 5.7 在线启用和关闭GTID
1.相关基础 MySQL 5.7.6之后GTID_MODE提供了两个新的选项分别为ON_PERMISSIVE和OFF_PERMISSIVEOFF_PERMISSIVE:不产生GTID事务, Slave ...
- java 程序设计第三次作业内容
第一题:输出结果是什么? System.out.println("5+5="+5+5); 第二题:输出结果是什么? int a=3,b; b=a++; sop("a=&q ...
- SpringBoot之自动配置原理
我在前面的Helloworld的程序中已经分析过一次,配置原理了: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@En ...
- tab菜单的点击的动态效果和内容页面的关联显示jQuery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 01 python爬虫
---
- JVM 内存分配和回收策略
对象的内存分配,主要是在java堆上分配(有可能经过JIT编译后被拆为标量类型并间接地在栈上分配),如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配.少数情况下也是直接分配到老年代,分配规则不 ...
- 使用U盘给笔记本重做系统
**一.戴尔 Vostro 14 3000 Series **1. 开机时快速按F12进入BIOS界面 **2. 按照下图进行一系列的处理,把U盘被设置为第一启动项 **3. 插入U盘后进入老毛桃PE ...