思路:首先如果颜色相同直接利用以前的答案即可,可以离线排序或是在线hash,然后考虑怎么快速统计答案。

首先如果点a是点b的祖先,那么一定有点b在以点a为根的子树的dfs序区间内的,于是先搞出dfs序。

然后如果颜色a的点数很小,颜色b的点数很大,那么可以考虑枚举a的点数,然后对于每一种颜色开个vector记录一下有哪些点是这种颜色,然后按照它们的dfs序排序,就可以用颜色a中的每个点在颜色b中二分出哪些点属于以该点为根的子树对应的dfs序区间了。复杂度O(size(a)*log(size(b))),size(a)表示颜色a的vector的size()。

然后如果颜色b的点数很小,颜色a的点数很大,那么就枚举b的点数,这时要考虑的问题就成了一个点被多少段区间覆盖了,然后离散化差分预处理,再去二分(我写的是vector的离散化)。复杂度O(size(b)*log(size(a)))

但如果a,b的点数差不多且都很大(也就是几乎为sqrt(n)),那么算法复杂度就会变成O(sqrt(n)*log(n))了,再乘以一个q就会GG,于是只能另寻他法,然后可以发现直接两个指针扫过去,一个扫区间端点另一个扫要询问的点,然后如果扫到一个点就直接统计答案,然后这就变成了O(size(a)+size(b))了。

那这个很大是有多大,很小是有多小呢?

对于第一种算法使用条件是size(b)>x,第二种算法使用条件是size(a)>x,其余则用第三种算法。

对于第一、二种情况,时间复杂度最大是O(n^2logn/x),然后对于第三种则是O(n*x),然后根据基本不等式x=sqrt(nlogn),总时间复杂度为O(n*sqrt(nlogn))。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define maxn 200005
#define maxr 30000 int n,r,Q,tot,cnt;
int now[maxn],pre[*maxn],son[*maxn],color[maxn],dfn[maxn],size[maxn];
long long ans[maxn]; inline int read(){
int x=,f=;char ch=getchar();
for (;ch<''||ch>'';ch=getchar()) if (ch=='-') f=-;
for (;ch>=''&&ch<='';ch=getchar()) x=x*+ch-'';
return x*f;
} struct node{
int dfn,bo;
node(){}
node(int a,int b){dfn=a,bo=b;}
bool operator <(const node &a)const{return dfn<a.dfn;}
}; struct query{
int x,y,id;
bool operator <(const query &a)const{return x<a.x||(x==a.x&&y<a.y);}
}q[maxn]; bool cmp(int a,int b){return dfn[a]<dfn[b];} vector<int> col[maxr],val[maxr];
vector<node> v[maxr];
vector<int> fuckpps[maxr]; void add(int a,int b){
son[++tot]=b;
pre[tot]=now[a];
now[a]=tot;
} void link(int a,int b){
add(a,b),add(b,a);
} void dfs(int x,int fa){
dfn[x]=++cnt;
for (int p=now[x];p;p=pre[p])
if (son[p]!=fa) dfs(son[p],x),size[x]+=size[son[p]]+;
} int binary_search(int l,int r,int b,int pos){
int ans=-;
while (l<=r){
int mid=(l+r)>>;
if (pos>=fuckpps[b][mid]) ans=mid,l=mid+;
else r=mid-;
}
return ans+;
} long long solve1(int a,int b){
long long ans=;
for (unsigned int i=;i<col[a].size();i++){
int x=col[a][i],l=binary_search(,fuckpps[b].size()-,b,dfn[x]-),r=binary_search(,fuckpps[b].size()-,b,dfn[x]+size[x]);
ans+=r-l;
}
return ans;
} int binary_search2(int l,int r,int b,int pos){
int ans=-;
while (l<=r){
int mid=(l+r)>>;
if (v[b][mid].dfn<=pos) ans=mid,l=mid+;
else r=mid-;
}
return ans;
} long long solve2(int a,int b){
long long ans=;
for (unsigned int i=;i<col[b].size();i++){
int x=col[b][i],pos=binary_search2(,v[a].size()-,a,dfn[x]);
if (pos!=-) ans+=val[a][pos];
}
return ans;
} long long solve3(int a,int b){
long long ans=;unsigned int i=,j=,tt=;
while (i<v[a].size() && j<col[b].size())
if (v[a][i].dfn<=dfn[col[b][j]]) tt=val[a][i],i++;else ans+=tt,j++;
return ans;
} int main(){
n=read(),r=read(),Q=read();int siz=sqrt(n*log2(n));
for (int i=,x;i<=n;i++){
if (i!=) x=read(),link(i,x);
color[i]=read();col[color[i]].push_back(i);
}
dfs(,);
for (int i=;i<=n;i++) fuckpps[color[i]].push_back(dfn[i]);
for (int i=;i<=r;i++) sort(col[i].begin(),col[i].end(),cmp),sort(fuckpps[i].begin(),fuckpps[i].end());
for (int i=;i<=r;i++){
for (unsigned int j=;j<col[i].size();j++)
v[i].push_back(node(dfn[col[i][j]],)),v[i].push_back(node(dfn[col[i][j]]+size[col[i][j]]+,-));
sort(v[i].begin(),v[i].end());int sum=;
for (unsigned int j=;j<v[i].size();j++){
sum+=v[i][j].bo;
val[i].push_back(sum);
}
}
for (int i=;i<=Q;i++) q[i].x=read(),q[i].y=read(),q[i].id=i;
sort(q+,q+Q+);
for (int i=;i<=Q;i++){
if (q[i].x==q[i-].x && q[i].y==q[i-].y){ans[q[i].id]=ans[q[i-].id];continue;}
if (col[q[i].y].size()+>=siz&&col[q[i].x].size()+<siz) ans[q[i].id]=solve1(q[i].x,q[i].y);
else if (col[q[i].x].size()+>=siz&&col[q[i].y].size()+<siz) ans[q[i].id]=solve2(q[i].x,q[i].y);
else ans[q[i].id]=solve3(q[i].x,q[i].y);
}
for (int i=;i<=Q;i++) printf("%lld\n",ans[i]);
return ;
}

bzoj3351:[ioi2009]Regions的更多相关文章

  1. BZOJ3351: [ioi2009]Regions(根号分治)

    题意 题目链接 Sol 很神仙的题 我们考虑询问(a, b)(a是b的祖先),直接对b根号分治 如果b的出现次数\(< \sqrt{n}\),我们可以直接对每个b记录下与它有关的询问,这样每个询 ...

  2. 【dfs序】【二分】【主席树】【分块】bzoj3351 [ioi2009]Regions

    http://dzy493941464.sinaapp.com/archives/96 那个SIZE貌似必须设成R*R/Q?不知为啥,自己算的不是这个的说. 本机AC,线上TLE. #include& ...

  3. LeetCode130:Surrounded Regions

    题目: Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is capt ...

  4. [LeetCode]题解(python):130-Surrounded Regions

    题目来源: https://leetcode.com/problems/surrounded-regions/ 题意分析: 给定给一个二维的板,这个板只包括‘X’和‘O’.将被‘X’包围的‘O’变成‘ ...

  5. BZOJ.3351.[IOI2009]Regions(根号分治 差分)

    BZOJ 表示非常爽2333 \(Description\) 给定一棵\(n\)个点的树,每个点有一个属性\(1\leq r_i\leq R\). \(Q\)次询问,每次询问给定\(r1,r2\),求 ...

  6. BZOJ 3351: [ioi2009]Regions

    对于一个询问(x,y)对y出现次数分类,若<=lim,在儿子处统计答案,若>lim则y的种类肯定<lim,在祖先处统计(仿佛要去重?但是没去重也过了,那个时限仿佛怎么做都能过) #i ...

  7. MaskRCNN:三大基础结构DeepMask、SharpMask、MultiPathNet

    MaskXRCnn俨然成为一个现阶段最成功的图像检测分割网络,关于MaskXRCnn的介绍,需要从MaskRCNN看起. 当然一个煽情的介绍可见:何恺明团队推出Mask^X R-CNN,将实例分割扩展 ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. [LeetCode] Walls and Gates 墙和门

    You are given a m x n 2D grid initialized with these three possible values. -1 - A wall or an obstac ...

随机推荐

  1. Eclipse创建Maven Web项目 + 测试覆盖率 + 常见问题(2015.07.14——湛耀)

    Eclipse创建Maven web项目: 到此,并没有创建好,接下来一步步解决问题: 问题:无法创建src/main/java目录 解决: 右键项目选择[properties] 点击[OK] 问题: ...

  2. 非常实用的Android Studio快捷键

    One—打印Log 生成tag: logt 打印log: logm logd loge Two—代码提示 Ctrl + Alt + Space Three—代码移动 选中代码: Ctrl + w 向 ...

  3. context-param和init-param区别

    转载 http://www.cnblogs.com/hzj-/articles/1689836.html <context-param>的作用:web.xml的配置中<context ...

  4. C# ip hash算法实现ip分流

    private void button42_Click(object sender, EventArgs e) { Dictionary<int, string> proxyIpNodes ...

  5. Objective C assign&copy & retain区别

    什么是assign,copy,retain之间的区别? assign: 简单赋值,不更改索引计数(Reference Counting). copy: 建立一个索引计数为1的对象,然后释放旧对象 re ...

  6. [Javascript] Chaining the Array map and filter methods

    Both map and filter do not modify the array. Instead they return a new array of the results. Because ...

  7. 常用工具之stunnel

    The stunnel program is designed to work as an SSL encryption wrapper between remote client and local ...

  8. iOS开发经验总结(上)

    在iOS开发中经常需要使用的或不常用的知识点的总结,几年的收藏和积累(踩过的坑). 一. iPhone Size 手机型号 屏幕尺寸 iPhone 4 4s 320 * 480 iPhone 5 5s ...

  9. list add元素覆盖之前元素问题思考

    最近码墙时发现了一个很有意思的问题,定义一个引用对象,如果在循环外面定义对象,在循环里list.add(对象),最后的结果却是所有的对象值都是一样的,即每add一次,都会把之前所有的数据覆盖掉,蛮有趣 ...

  10. javascript笔记09:javascript的下拉式导航菜单

    <!DOCTYPE html> <html> <body> <script> function hideAll() { for(i=0;i<odi ...