【SPOJ10707】 COT2 Count on a tree II
SPOJ10707 COT2 Count on a tree II
Solution
我会强制在线版本! Solution戳这里
代码实现
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi()
{
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int N=60010;
int Bl[N],B,P[N],ans[310][N],a[N],b[N],bl[N],num,p[N][310],Anum,rt[310],F[N];
struct array
{
int num[210];
int operator[](int x){return p[num[Bl[x]]][P[x]];};
void insert(const array &pre,int x,int dep)
{
int block=Bl[x],t=P[x];
memcpy(num,pre.num,sizeof(num));
memcpy(p[++Anum],p[num[block]],sizeof(p[0]));
p[Anum][t]=dep;num[block]=Anum;
}
}s[N];
int to[N<<1],nxt[N<<1],front[N],cnt,dep[N],f[N][22],st[N],sta,kind;
inline void Add(int u,int v)
{
to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
}
inline int dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
f[u][0]=fa;
s[u].insert(s[fa],a[u],dep[u]);
st[++sta]=u;int mx=dep[u],now=sta;
for(re int i=front[u];i;i=nxt[i])
{
int v=to[i];
if(v==fa)continue;
mx=max(mx,dfs(v,u));
}
if(mx-dep[u]>=B || now==1)
{
rt[++num]=u;
for(re int i=now;i<=sta;i++)bl[st[i]]=num;
sta=now-1;return dep[u]-1;
}
return mx;
}
int lca(int u,int v)
{
if(dep[u]<dep[v])swap(u,v);
for(re int i=20;~i;i--)
if(dep[u]-(1<<i)>=dep[v])u=f[u][i];
if(u==v)return u;
for(re int i=20;~i;i--)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
inline void getans(int u,int fa,int BL)
{
if(++F[a[u]]==1)kind++;
ans[BL][u]=kind;
for(re int i=front[u];i;i=nxt[i])
{
int v=to[i];
if(v==fa)continue;
getans(v,u,BL);
}
if(--F[a[u]]==0)kind--;
}
int solve_same(int x,int y)
{
sta=0;
for(kind=0;x!=y;x=f[x][0])
{
if(dep[x]<dep[y])swap(x,y);
if(!F[a[x]]++)++kind,st[++sta]=a[x];
}
int QAQ=kind+(!F[a[x]]);
for(;sta;sta--)F[st[sta]]=0;
return QAQ;
}
int solve_diff(int x,int y)
{
if(dep[rt[bl[x]]]<dep[rt[bl[y]]])swap(x,y);
int sum=ans[bl[x]][y];
int z=rt[bl[x]],d=dep[lca(x,y)];
sta=0;
for(;x!=z;x=f[x][0])
{
if(!F[a[x]] && s[z][a[x]]<d && s[y][a[x]]<d)
F[st[++sta]=a[x]]=1,sum++;
}
for(;sta;sta--)F[st[sta]]=0;
return sum;
}
int n,m;
void print(int x)
{
if(x>=10)print(x/10);
putchar(x%10+'0');
}
int main()
{
n=gi();m=gi();B=sqrt(n);
for(int i=1;i<=n;i++)Bl[i]=(i-1)/B+1,P[i]=i%B;
for(re int i=1;i<=n;i++)a[i]=b[i]=gi();
sort(b+1,b+n+1);int N=unique(b+1,b+n+1)-b-1;
for(re int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+N+1,a[i])-b;
for(re int i=1;i<n;i++)
{
int u=gi(),v=gi();
Add(u,v);Add(v,u);
}
dfs(1,1);
for(re int i=1;i<=num;i++)getans(rt[i],rt[i],i);
for(re int j=1;j<=20;j++)
for(re int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
int lastans=0;
while(m--)
{
int u=gi(),v=gi();
if(bl[u]==bl[v])lastans=solve_same(u,v);
else lastans=solve_diff(u,v);
print(lastans);putchar('\n');
}
return 0;
}
【SPOJ10707】 COT2 Count on a tree II的更多相关文章
- 【SPOJ10707】COT2 - Count on a tree II
题目大意:给定一棵 N 个节点的无根树,每个节点有一个颜色.现有 M 个询问,每次询问一条树链上的不同颜色数. 题解:学会了树上莫队. 树上莫队是将节点按照欧拉序进行排序,将树上问题转化成序列上的问题 ...
- 【树上莫队】【SP10707】 COT2 - Count on a tree II
Description 给定一棵 \(n\) 个点的树,每个节点有一个权值,\(m\) 次询问,每次查询两点间路径上有多少不同的权值 Input 第一行是 \(n\) 和 \(m\) 第二行是 \(n ...
- 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 COT2 - Count on a tree II 【树上莫队】
题目分析: 考虑欧拉序,这里的欧拉序与ETT欧拉序的定义相同而与倍增LCA不同.然后不妨对于询问$u$与$v$让$dfsin[u] \leq dfsin[v]$,这样对于u和v不在一条路径上,它们可以 ...
- 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)
http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...
- 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上面这个人推导部分写 ...
随机推荐
- 从hash算法到java hashcode()
转载 https://blog.csdn.net/Walk_er/article/details/74976146 hash算法是一个摘要算法(yy:描述性算法:可以给一个物体确切的描述,但是不能通过 ...
- Linux CPU Hotplug CPU热插拔
http://blog.chinaunix.net/uid-15007890-id-106930.html CPU hotplug Support in Linux(tm) Kernel Linu ...
- JS高级- OOP-ES5
1. OOP 面向对象三大特点: 封装,继承,多态 封装: 问题: 构造函数可重用代码和结构定义,但无法节约内存 为什么: 放在构造函数内的方法定义,每new一次,都会反复创建副本——浪费内存 解决: ...
- Java第11章笔记
什么是类,什么是对象 举例说明什么是类,什么是对象? 一句话:万物皆对象 类的概念:类是具有相同属性和服务的一组对象的集合. 1.为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个部分 ...
- ODT(old driver tree)详解(带例题)
文章目录 ODT简介 实现前提&&实现原理 初始化 split操作 assign操作 其它操作 区间第k小 区间加 区间所有数的k次方和 几道水题 ODT简介 ODT(old driv ...
- RNN文章总结
1.RNN 基本结构类型 2. RNN 3.零基础入门深度学习(5) - 循环神经网络 4.
- 关于DOM级别的一些问题,DOM0,DOM1,DOM2
之前看书没太注意这个问题,直到我今天看书看到一个DOM0级,于是我就在群里问了下各个级别的意思区别.. 首先我们的确定标准了是没有DOM0级的.在平时阅读的时候可能会读到DOM0级(DOM Level ...
- adb push init.rc /
http://blog.csdn.net/jumper511/article/details/28856249 修改Android init.rc文件后,需要将修改后的文件上传到手机,但是发下如下问题 ...
- 实用shell命令100条
1,echo "aa" > test.txt 和 echo "bb" >> test.txt //>将原文件清空,并且内容写入到文件中, ...
- 【python-crypto】导入crypto包失败的情况,怎么处理
[python-crypto]导入crypto包失败的情况,怎么处理 是因为你自己安装的python的版本太高,所以自己降版本吧,捣鼓了一下午 pip install crypto pip insta ...