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

思路:树上莫队的模板题

LCA用tarjan算法来找,可以变成DFS以后的序列,然后再用莫队算法的思路。

#include <bits/stdc++.h>

using namespace std;
int const SIZE=40100;
int const BLOCK_SIZE=300; //利用hash记录LCA
struct Hash{
typedef struct __t{int a;int b;__t(int aa=0,int bb=0):a(aa),b(bb){}}key_t;
typedef int value_t;
enum{MOD=0x1fffff};
key_t keys[MOD+1];
value_t values[MOD+1]; int head[MOD+1];
int next[MOD+1];
int toUsed; Hash():toUsed(0){fill(head,head+MOD+1,-1);} void clear(){fill(head,head+MOD+1,-1);toUsed=0;} int getKey(key_t const&key)const {
int ret=17;
ret=ret*37+key.a;
ret=ret*37+key.b;
return ret;
} void insert(key_t const&key,value_t const&value){
int k = getKey(key) & MOD;
keys[toUsed] = key;
values[toUsed] = value;
next[toUsed] = head[k];
head[k] = toUsed++;
} value_t find(key_t const&key)const{
int k = getKey(key) & MOD;
for(int i=head[k];i!=-1;i=next[i]){
if ( keys[i].a == key.a && keys[i].b == key.b ) return values[i];
}
return 0;
} void disp(FILE*fp)const{
for(int i=1;i<toUsed;++i){
fprintf(fp,"(%d %d): %d\n",keys[i].a,keys[i].b,values[i]);
}
}
}Lca; struct dege_t{
int to;
int next;
}Edge[SIZE<<1]; int ECnt=1;
int Vertex[SIZE]={0}; inline void makeEdge(int a,int b)
{
Edge[ECnt].to=b;
Edge[ECnt].next=Vertex[a];
Vertex[a]=ECnt++; Edge[ECnt].to=a;
Edge[ECnt].next=Vertex[b];
Vertex[b]=ECnt++;
} //生成DFS序
int InIdx[SIZE],OutIdx[SIZE];
int NewIdx[SIZE<<1];
int NCnt = 1;
void dfs(int node,int parent){
NewIdx[NCnt] = node;
InIdx[node] = NCnt++;
for(int next=Vertex[node];next;next=Edge[next].next){
int to = Edge[next].to;
if ( to != parent ) dfs(to,node);
}
NewIdx[NCnt] = node;
OutIdx[node] = NCnt++;
} //Tarjan算法中用到的并查集
int Father[SIZE];
int find(int x){return x==Father[x]?x:Father[x]=find(Father[x]);} bool Flag[SIZE] = {false};
vector<vector<int> > Questions(SIZE,vector<int>()); //Tarjan算法一次性求出所有的LCA
void Tarjan(int u,int parent){
Father[u] = u;
Flag[u] = true; for(int next=Vertex[u];next;next=Edge[next].next){
int to = Edge[next].to;
if ( to == parent ) continue;
Tarjan(to,u);
Father[to] = u;
} vector<int>&vec=Questions[u];
for(vector<int>::iterator it=vec.begin();it!=vec.end();++it){
int v = *it;
if ( Flag[v] ){
int r = find(v);
Lca.insert(Hash::key_t(u,v),r);
Lca.insert(Hash::key_t(v,u),r);
}
}
} struct _t{
int s,e;
int idx;
int lca;
}; bool operator < (_t const&lhs,_t const&rhs){
int ln = lhs.s / BLOCK_SIZE;
int rn = rhs.s / BLOCK_SIZE;
return ln < rn || ( ln == rn && lhs.e < rhs.e );
}
int N,M;
int A[SIZE];
_t B[100000]; //将原树上的路径问题转化为DFS序中的区间问题
inline void mkQuestion(int a,int b,int idx){
int lca = Lca.find(Hash::key_t(a,b));
if ( lca == a || lca == b ){
int t = lca == a ? b : a;
B[idx].s = OutIdx[t];
B[idx].e = OutIdx[lca];
B[idx].lca = 0;
}else{
B[idx].lca = lca;
if ( OutIdx[a] < InIdx[b] ) B[idx].s = OutIdx[a], B[idx].e = InIdx[b];
else B[idx].s = OutIdx[b], B[idx].e = InIdx[a];
}
} int MoAns;
int Ans[100000],Cnt[SIZE];
inline void insert(int n){
if ( 1 == ++Cnt[n] ) ++MoAns;
} inline void remove(int n){
if ( 0 == --Cnt[n] ) --MoAns;
} void MoOp(int idx){
int k = NewIdx[idx];
if ( Flag[k] ) remove(A[k]);
else insert(A[k]);
Flag[k] ^= 1;
}
void Mo(){
sort(B,B+M); fill(Flag,Flag+N+1,false);
int curLeft = 1;
int curRight = 0;
MoAns = 0; for(int i=0;i<M;++i){
while( curRight < B[i].e ) MoOp(++curRight);
while( curLeft > B[i].s ) MoOp(--curLeft);
while( curRight > B[i].e ) MoOp(curRight--);
while( curLeft < B[i].s ) MoOp(curLeft++);
if ( B[i].lca ){
Ans[B[i].idx] = MoAns + ( 0 == Cnt[A[B[i].lca]] ? 1 : 0 );
}else{
Ans[B[i].idx] = MoAns;
} }
}
void init(int n){
ECnt = NCnt = 1;
fill(Vertex,Vertex+n+1,0);
fill(Flag,Flag+n+1,false);
}
int getUnsigned(){
char ch = getchar();
while( ch > '9' || ch < '0' ) ch = getchar(); int ret = 0;
do ret = ret * 10 + (int)(ch-'0');while( '0' <= (ch=getchar()) && ch <= '9' );
return ret;
} int W[SIZE];
bool read(){
if ( EOF == scanf("%d",&N) ) return false;
M = getUnsigned(); init(N); //权值输入并离散化
for(int i=1;i<=N;++i) W[i] = A[i] = getUnsigned();
sort(W+1,W+N+1);
int* pn = unique(W+1,W+N+1);
for(int i=1;i<=N;++i) A[i] = lower_bound(W+1,pn,A[i]) - W; int a,b;
for(int i=1;i<N;++i){
a = getUnsigned();
b = getUnsigned();
makeEdge(a,b);
}
dfs(1,0); for(int i=0;i<M;++i){
B[i].s = getUnsigned();
B[i].e = getUnsigned();
B[i].idx = i;
Questions[B[i].s].push_back(B[i].e);
Questions[B[i].e].push_back(B[i].s);
} Tarjan(1,0);
for(int i=0;i<M;++i) mkQuestion(B[i].s,B[i].e,i); return true;
}
int main(){
//freopen("1.txt","r",stdin);
while ( read() ){
Mo();
for(int i=0;i<M;++i)printf("%d\n",Ans[i]);
}
return 0;
}

COT2 - Count on a tree II(树上莫队)的更多相关文章

  1. spoj COT2 - Count on a tree II 树上莫队

    题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的,  受益匪浅.. #include <iostream> #include < ...

  2. SP10707 COT2 - Count on a tree II (树上莫队)

    大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...

  3. SP10707 COT2 - Count on a tree II [树上莫队学习笔记]

    树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...

  4. SPOJ COT2 Count on a tree II 树上莫队算法

    题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...

  5. [SPOJ]Count on a tree II(树上莫队)

    树上莫队模板题. 使用欧拉序将树上路径转化为普通区间. 之后莫队维护即可.不要忘记特判LCA #include<iostream> #include<cstdio> #incl ...

  6. 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  ...

  7. 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 ...

  8. 【SPOJ10707】 COT2 Count on a tree II

    SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...

  9. SPOJ COT2 Count on a tree II (树上莫队,倍增算法求LCA)

    题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无 ...

随机推荐

  1. 【APUE】进程间通信之FIFO

    FIFO也称为有名管道,它是一种文件类型,是半双工的.FIFO简单理解,就是它能把两个不相关的进程联系起来,FIFO就像一个公共通道,解决了不同进程之间的“代沟”.普通的无名管道只能让相关的进程进行沟 ...

  2. 为什么java构造函数的构造器只能在第一行写this() 或者super() ?

    最近在看内部类, 但是被“为什么匿名内部类或者局部内部类使用方法的局部变量时, 局部变量一定得是final类型”困扰着, 在网上查找资料的时候, 发现我对类初始化完全不了解, 之前的认识都是错误! 所 ...

  3. 【剑指offer】数组中仅仅出现一次的数字(1)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/27649027 题目描写叙述: 一个整型数组里除了两个数字之外.其它的数字都出现了两次. 请 ...

  4. 微软Build2016:Xamarin杂记

    去年的Build2015技术大会.留给人印象最深的莫过是Windows 10在手机端.PC端.Xbox等硬件平台上的大一统.还有非常具有科幻气质的HoloLens技术的各种展示.去年尽管也展示了Xam ...

  5. 【翻译自mos文章】在12c中Create or Truncate Table时非常慢,等待事件为 DFS Lock Handle wait

    来源于: Create or Truncate Table Slow in 12c While Waiting for DFS Lock Handle wait (文档 ID 2085308.1) A ...

  6. 【hadoop】ssh localhost 免密码登陆(图解)

    假设系统中有用户test,属于用户组test, 1. 首先确认能否不输入口令就用ssh登录localhost: $ ssh localhost 输出如下所示: 2. 如果不输入口令就无法用ssh登陆l ...

  7. atom及其插件activate-power-mode下载安装

    Atom是Github推出的一个文本编辑器,其中包含很多插件可以自行下载安装,其中一个最近比较火的就是插件activate-power-mode,可以实现打字屏振效果, 打字带特效哦,所以最近就尝试安 ...

  8. beego6

    package main //beego使用的是go语言原生的模版 import ( //_ "beego1/routers" //默认controll文件夹里面的控制器 &quo ...

  9. 一步一步学Silverlight 2系列(3):界面布局

    述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...

  10. HTTP传输二进制初探

    [转]HTTP传输二进制初探 http://www.51testing.com/?uid-390472-action-viewspace-itemid-233993 [转]HTTP传输二进制初探 上一 ...