bzoj3351:[ioi2009]Regions
思路:首先如果颜色相同直接利用以前的答案即可,可以离线排序或是在线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的更多相关文章
- BZOJ3351: [ioi2009]Regions(根号分治)
题意 题目链接 Sol 很神仙的题 我们考虑询问(a, b)(a是b的祖先),直接对b根号分治 如果b的出现次数\(< \sqrt{n}\),我们可以直接对每个b记录下与它有关的询问,这样每个询 ...
- 【dfs序】【二分】【主席树】【分块】bzoj3351 [ioi2009]Regions
http://dzy493941464.sinaapp.com/archives/96 那个SIZE貌似必须设成R*R/Q?不知为啥,自己算的不是这个的说. 本机AC,线上TLE. #include& ...
- LeetCode130:Surrounded Regions
题目: Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is capt ...
- [LeetCode]题解(python):130-Surrounded Regions
题目来源: https://leetcode.com/problems/surrounded-regions/ 题意分析: 给定给一个二维的板,这个板只包括‘X’和‘O’.将被‘X’包围的‘O’变成‘ ...
- BZOJ.3351.[IOI2009]Regions(根号分治 差分)
BZOJ 表示非常爽2333 \(Description\) 给定一棵\(n\)个点的树,每个点有一个属性\(1\leq r_i\leq R\). \(Q\)次询问,每次询问给定\(r1,r2\),求 ...
- BZOJ 3351: [ioi2009]Regions
对于一个询问(x,y)对y出现次数分类,若<=lim,在儿子处统计答案,若>lim则y的种类肯定<lim,在祖先处统计(仿佛要去重?但是没去重也过了,那个时限仿佛怎么做都能过) #i ...
- MaskRCNN:三大基础结构DeepMask、SharpMask、MultiPathNet
MaskXRCnn俨然成为一个现阶段最成功的图像检测分割网络,关于MaskXRCnn的介绍,需要从MaskRCNN看起. 当然一个煽情的介绍可见:何恺明团队推出Mask^X R-CNN,将实例分割扩展 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- [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 ...
随机推荐
- HDOJ-ACM1020(JAVA)
题意:给字母计数,如果是字母后面没有相同的,原样输出,如果有则输出这个字母的个数和字母本身. import java.util.*; import java.io.*; public class Ma ...
- ZOJ-3725 Painting Storages DP
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3725 n个点排列,给每个点着色,求其中至少有m个红色的点连续的数 ...
- Native code - how to get function call stack (backtrace) programatically 附带源代码
自己根据 https://github.com/zhuowei/libcorkscrew-ndk 上的库做了一个包装库并附带使用的例子(executable 分支),具体代码在自己的代码仓库里,名字叫 ...
- ffmpeg关于aac解码
ffmpeg从0.11.3版本开始,默认解码aac为AV_SAMPLE_FMT_FLT (float) 0.11.2以前版本解码aac为AV_SAMPLE_FMT_S16 (16位short型)
- MySQL开发中常用的查询语句总结
1.查询数值型数据: SELECT * FROM tb_name WHERE sum > 100; 查询谓词:>,=,<,<>,!=,!>,!<,=>, ...
- 对css中的定位属性postion刨根解牛
定位的基本思想很简单: 它允许你定义元素框相对于其正常位置应该出现的位置(relative),或者相对于父元素(absolute).另一个元素甚至浏览器窗口本身的位置(fixed).显然,这个功能非常 ...
- Selenium 进行web自动化测试
1.安装火狐版本时注意,如果无法正常安装,应该点击右键---以管理员身份运行 2.安装成功后,选择工具--选项--高级--更新,停止其自动化更新 3.maven里面加载应有的selenium的组件
- linux命令之nohup
功能: 使进程在退出登录后仍旧继续执行,nohup就是不挂起的意思(no hang up). 格式:$nohup command 和 $nohup command & 两种,二者之间的区别就是 ...
- 启用PowerShell Web Access
Windows PowerShell Web Access(PSWA)是 Windows Server 2012 中的新功能,充当 Windows PowerShell 网关,允许远程计算机基于 We ...
- Java编程思想第四版*第七章*个人练习
欢迎加群:239063848 成团的笔记:该组仅用于技术共享和交流,问题和答案公布 潘基聊天.禁止广告.禁止招聘-- 练习1:(2)创建一个简单的类.第二个类中,将一个引用定义为第一个类的对象.运用惰 ...