SPOJcot2 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
题意:求两点间点权值的种类数量。
之前讲过了如何“皇室联邦分块”,由于此题没有要求在线,就先分块,然后莫队就行了。
每次转移的时候怕出错,就干脆vis标记即可。
此题还有很多在线的做法。强得不行。。。ORZ
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
const int maxm=;
int n,m,group[maxn]; struct in
{
int x; int y; int id;
friend bool operator< (in a,in b)
{
return group[a.x]!=group[b.x]?group[a.x]<group[b.x]:group[a.y]<group[b.y];
}
}q[maxm]; struct Solve
{
int maxi;
int Next[maxn<<],Laxt[maxn],To[maxn<<],cnt,delta;
int num[maxn],dep[maxn],anc[maxn][],w[maxn],wx[maxn];
int B,stc[maxn],top,tot,ans[maxm],vis[maxn]; int swap(int &u,int &v) { u^=v;v^=u;u^=v;}
int read()
{
int res=;bool t=false; char c=getchar();
while(c>''||c<'') { if(c=='-') t=true; c=getchar();}
while(c<=''&&c>='') { res=(res<<)+(res<<)+c-'';c=getchar();}
if(t) return -res; return res;
} void add(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt; To[cnt]=v;
} void init()
{
int u,v; B=sqrt(n);
for(int i=;(<<i)<=n;i++) maxi=i;
for(int i=;i<=n;i++) scanf("%d",&w[i]);
for(int i=;i<=n;i++) wx[i]=w[i];
sort(wx+,wx+n+);
int tt=unique(wx+,wx+n+)-(wx+);
for(int i=;i<=n;i++)
w[i]=lower_bound(wx+,wx+tt+,w[i])-wx;
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
dep[]=; dfs();
while(top) group[stc[top--]]=tot;//最后剩余部分莫忘liao。
for(int i=;i<=m;i++) {
q[i].id=i, scanf("%d%d",&q[i].x,&q[i].y);
if(group[q[i].x]<group[q[i].y]) swap(q[i].x,q[i].y);//稍微调整一下,可能会优化。
}
sort(q+,q+m+); get_LCA();
} void dfs(int u)
{
int Now=top;
for(int i=Laxt[u];i;i=Next[i])
if(!dep[To[i]]){
anc[To[i]][]=u; dep[To[i]]=dep[u]+; dfs(To[i]);
if(top-Now>=B) {
++tot; while(top!=Now) group[stc[top--]]=tot;
}
}
stc[++top]=u;
} void get_LCA()
{
for(int i=;i<=maxi;i++)
for(int j=;j<=n;j++)
anc[j][i]=anc[anc[j][i-]][i-];
} int LCA(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
for(int i=maxi;i>=;i--)
if(dep[anc[u][i]]>=dep[v]) u=anc[u][i];
if(u==v) return u;
for(int i=maxi;i>=;i--){
if(anc[u][i]!=anc[v][i]){
u=anc[u][i];
v=anc[v][i];
}
} return anc[u][];
} void trans(int &u)
{
if(vis[u]) //已被记录,则本次去掉此点
{
if(--num[w[u]] == ) delta--;
}
else if(++num[w[u]] == ) delta++;
vis[u] ^= ;
u=anc[u][];
} void solve()
{
int su=,sv=; delta=;
for(int i = ; i <= m; i++)
{
int tu=q[i].x,tv=q[i].y;
int lca=LCA(su, tu);//两点朝lca移动,处理路径上的点
while(su!=lca) trans(su);
while(tu!=lca) trans(tu);
lca=LCA(sv,tv);
while(sv!=lca) trans(sv);
while(tv!=lca) trans(tv);
su=q[i].x,sv=q[i].y;
lca=LCA(sv, su);
ans[q[i].id]=delta+(!num[w[lca]]);//对lca特殊处理
}
for(int i=;i<=m;i++) printf("%d\n",ans[i]);
}
}Tree;
int main()
{
scanf("%d%d",&n,&m);
Tree.init();
Tree.solve();
return ;
}
SPOJcot2 Count on a tree II (树上莫队)的更多相关文章
- spoj COT2 - Count on a tree II 树上莫队
题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的, 受益匪浅.. #include <iostream> #include < ...
- SP10707 COT2 - Count on a tree II (树上莫队)
大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...
- [SPOJ]Count on a tree II(树上莫队)
树上莫队模板题. 使用欧拉序将树上路径转化为普通区间. 之后莫队维护即可.不要忘记特判LCA #include<iostream> #include<cstdio> #incl ...
- SP10707 COT2 - Count on a tree II [树上莫队学习笔记]
树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...
- SPOJ COT2 Count on a tree II 树上莫队算法
题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...
- SPOJCOT2 Count on a tree II
分析 树上莫队裸题. 好博客 树剖的时候不能再次dfs重儿子.(好像是废话,但我因为这个问题调了三小时) 代码 #include<cstdlib> #include<cstdio&g ...
- P4074 [WC2013]糖果公园 树上莫队带修改
题目链接 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩. 糖果公园的结构十分奇特,它由 nn 个游览点构 ...
- 【SPOJ】Count On A Tree II(树上莫队)
[SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...
- 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 ...
随机推荐
- 转: linux下的自动对时
转自: http://www.cnblogs.com/vimmer/archive/2012/05/17/2505785.html 评注:date 命令格式为: date -s 2012-08-02 ...
- vue2.0 + vux 项目搭建
1.快速搭建项目模板 因为项目使用vux,所以推荐使用vux官网的airyland/vux2 模板,vue-cli工具是vue项目的搭建脚手架 默认为 webpack2 模板,如果你需要使用webpa ...
- IOS_DatePicker_PickerView_SegmentControl_键盘处理
H:/0712/01_UIController_MJViewController.m // MJViewController.m // 01-总结复习 // Created by apple on 1 ...
- python正则方法
通过正则替换字符串 res=re.sub(正则,newString,srcString)//返回替换后的字符串 res,m=res.subn(正则,newString,srcString)//返回替换 ...
- mysql: 关于MySQL InnoDB锁行还是锁表?
baidu zone - 关于MYSQL Innodb 锁行还是锁表,深入讲解
- python--函数嵌套 命名空间
函数的嵌套调用 def func(): print(123) def func2(): func() print(345) func2() #结果:123 345 函数的嵌套定义 def func() ...
- webstorm 设置IP 访问 手机测试效果
http://www.cnblogs.com/gulei/p/5126383.html 前端开发中,经常需要将做好的页面给其他同事预览或手机测试,之前一直用的第三方本地服务器usbwebserver, ...
- YARN和MapReduce的内存设置參考
怎样确定Yarn中容器Container,Mapreduce相关參数的内存设置,对于初始集群,由于不知道集群的类型(如cpu密集.内存密集)我们须要依据经验提供给我们一个參考配置值,来作为基础的配置. ...
- 后端程序员看前端想死(二)进入页面之后js分析
在上一篇中分析了一下以网页的组成.header中引入的乱七八糟的东西,现在进入到js中进行分析了 tuhooo啊,你是要搞前端了么? nonono,好玩,学一下 打开页面之后执行js的几种方法 直接写 ...
- php判断某字符串是否不以数字或其他特殊字符开头
if(preg_match("/^[^\d-.,:]/",$addr)){ echo $addr.'不是数字或其他特殊字符开头'; }