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上面这个人推导部分写 ...
随机推荐
-
LayaAir学习笔记
1.Text文本类 var Text=laya.display.Text; Laya.init(620,400); Laya.stage.bgColor="#323232";//设 ...
-
MFC 打开文件对话框 打开单个文件
CFileDialog的语法: CFileDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt=NULL,LPCTSTR lpszFileName=NULL,D ...
-
UIWebView的基本用法
一.UIWebView的基础使用 1.创建UIWebView: CGRect bouds = [[UIScreen manScreen]applicationFrame]; UIWebView* we ...
-
Browserify
NodeJS 把 JavaScript 的使用从浏览器端扩展到了服务器端,使得前端开发人员可以用熟悉的语言编写服务器端代码.这一变化使得 NodeJS 很快就流行起来.在 NodeJS 社区中有非常多 ...
-
[iOS问题归总]SourceTree+osChina版本管理出现的问题
1.commit失败(1) 解决办法: 把爆红的路径的文件删除掉, 重新commit 2. push时候, 有100MB限制 解决办法: Git只允许上传最大100MB的文件,如果超过,则会被serv ...
-
文本导出到pdf文件
程序中数据导出是经常有的需求,今天学习把文本导出到pdf文件.主要是用QPrinter,QPainter TextEditToPdf::TextEditToPdf(QWidget *parent, Q ...
-
HTTP中的重定向和请求转发的区别
原文出处:http://blog.csdn.net/meiyalei/article/details/2129120 一.调用方式 我们知道,在servlet中调用转发.重定向的语句如下: reque ...
-
LNMP的安装
一.安装Linux 安装某个linux桌面版系统,基本是ubuntu即可. 安装必要的库,如:pcre.xml.openssl.zlib等,sudo apt-get install libpcre3 ...
-
SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP
AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...
-
cmake简明使用指南
cmake简明使用指南 Last update 2018/8/8 先执行cmake生成makefile,然后看看里面的内容,(至少在ubuntu16.04上的cmake3.5.1上),有如下内容提供: ...