【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上面这个人推导部分写 ...
随机推荐
- 【转】C#异步的世界【下】
[转]C#异步的世界[下] 接上篇:<C#异步的世界[上]> 上篇主要分析了async\await之前的一些异步模式,今天说异步的主要是指C#5的async\await异步.在此为了方便的 ...
- QualNet/EXata的发展贯穿在美军网络中心战演进的始终
QualNet/EXata的发展贯穿在美军网络中心战演进的始终 赵玉亭 1. QualNet/EXata的前身GloMoSim是美国防部高级计划研究局(DARPA)在1994年启动的全球移动信息系 ...
- Java HttpURLConnection 下载图片 图片全是“加密图片”文字,怎么解决?
package com.qzf.util; import java.io.FileOutputStream;import java.io.IOException;import java.io.Inpu ...
- 2018.11.01 NOIP训练 梭哈(模拟)
传送门 这题貌似不考智商啊. 直接按题意写就可以了. 事实上把牌从小到大排序之后写起来很舒服的. 然后就是有些地方可以人脑减代码量和判断次数. (提示:满堂红和某几种同类型的牌的大小判断) 然后注意A ...
- boost--BOOST_AUTO、typeof、result_of
1.BOOST_AUTO BOOST_AUTO的功能类似于auto和any,可以用来定义任意类型数据,且可以在编译时自动推导出表达式的类型.BOOST_AUTO属于boost中的typeof库,使用需 ...
- C语言程序设计50例(三)(经典收藏)
[程序31]题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二个字母.1.程序分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母. ...
- 内联/块级元素的宽高及margin/padding的说明 |||||| 为何img、input等内联元素可以设置宽、高
1,内联非替换元素设置宽高是无效的,设置margin时,左右有效,上下无效.设置padding时,左右有效,而上下padding比较奇葩,内联非替换元素的上下padding会在元素内容盒不动的情况下上 ...
- w7 目录
第17章 期中架构体系介绍 期中架构环境准备 01-期中架构内容简介 02-期中架构大酒楼详解 03-期中架构使用到的软件简介 04-期中架构运维角度观察与使用的软件 05-重头开始创建一台新的虚拟机 ...
- 安卓修改开机logo
这里我们是在ubuntu下进行操作我是用root用户登陆的,首先安装netpbm库 执行:apt-get install netpbm 对于Android系统最开始表现logo是在内核当中,所以首先我 ...
- struts2访问web资源
通过ActionContext访问 public class TestActionContextAction { public String execute(){ //获取 ActionContext ...