BZOJ.3351.[IOI2009]Regions(根号分治 差分)
表示非常爽2333

\(Description\)
给定一棵\(n\)个点的树,每个点有一个属性\(1\leq r_i\leq R\)。
\(Q\)次询问,每次询问给定\(r1,r2\),求有多少点对\((x,y)\)满足,\(r_x=r1,\ r_y=r2\),且\(x\)是\(y\)的祖先。
\(n,q\leq2\times10^5,\ R\leq25000\)。
\(Solution\)
对属性为\(r2\)的有多少个点分类讨论。
若\(\leq\sqrt n\),在每个点处暴力统计它祖先的贡献;
若\(\gt\sqrt n\),则这样的属性不超过\(\sqrt n\)种,在属性为\(r1\)的点上暴力枚举这些\(r2\)更新答案(这里可以差分:进入子树前与访问完子树后)。
显然对于第二种情况,在每个点上,要对询问的\(r2\)去重才能保证复杂度(然而数据没卡不去重好像也能过...)。
关于如何去重,自己想的是,对\(r2\)相同的一些询问,要同时更新它们。大概以\(r2\)为关键字sort下,就可以差分了?
事实上对询问点对\((r1,r2)\)判一下重就可以了...如果出现够询问\((r1,r2)\),就直接用之前的作答案。
复杂度\(O(n\sqrt n+q\sqrt n)\)。
有树分块做法,然而懒得看。
//28360kb 7720ms
#include <map>
#include <cmath>
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<int,int>
#define gc() getchar()
#define MAXIN 500000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e5+5,M=25005;
int Enum,H[N],nxt[N],A[N],Ans[N];
std::vector<pr> v1[M],v2[M];
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline void AE(int u,int v)
{
nxt[v]=H[u], H[u]=v;
}
void DFS(int x)
{
static int sum1[N],sum2[N];
const std::vector<pr> &vec2=v2[A[x]];//一开始&忘了写...我说怎么MLE=-=
for(int i=0,l=vec2.size(); i<l; ++i)
Ans[vec2[i].second]+=sum2[vec2[i].first];
++sum1[A[x]], ++sum2[A[x]];
const std::vector<pr> &vec1=v1[A[x]];
for(int i=0,l=vec1.size(); i<l; ++i)
Ans[vec1[i].second]-=sum1[vec1[i].first];
for(int v=H[x]; v; v=nxt[v]) DFS(v);
for(int i=0,l=vec1.size(); i<l; ++i)
Ans[vec1[i].second]+=sum1[vec1[i].first];
--sum2[A[x]];
}
int main()
{
static int pos[N],cnt[M];
const int n=read(),R=read(),Q=read(),size=sqrt(n);
++cnt[A[1]=read()];
for(int i=2; i<=n; ++i) AE(read(),i), ++cnt[A[i]=read()];
std::map<pr,int> f;
std::map<pr,int>::iterator it;
for(int i=1; i<=Q; ++i)
{
int r1=read(),r2=read();
if((it=f.find(mp(r1,r2)))==f.end())
{
f[mp(r1,r2)]=pos[i]=i;
if(cnt[r2]<=size) v2[r2].push_back(mp(r1,i));
else v1[r1].push_back(mp(r2,i));
}
else pos[i]=it->second;
}
DFS(1);
for(int i=1; i<=Q; ++i) printf("%d\n",Ans[pos[i]]);//其实应该用long long的=v=
return 0;
}
BZOJ.3351.[IOI2009]Regions(根号分治 差分)的更多相关文章
- BZOJ3351: [ioi2009]Regions(根号分治)
题意 题目链接 Sol 很神仙的题 我们考虑询问(a, b)(a是b的祖先),直接对b根号分治 如果b的出现次数\(< \sqrt{n}\),我们可以直接对每个b记录下与它有关的询问,这样每个询 ...
- BZOJ 3351: [ioi2009]Regions
对于一个询问(x,y)对y出现次数分类,若<=lim,在儿子处统计答案,若>lim则y的种类肯定<lim,在祖先处统计(仿佛要去重?但是没去重也过了,那个时限仿佛怎么做都能过) #i ...
- BZOJ.4320.[ShangHai2006]Homework(根号分治 分块)
BZOJ \(\mathbb{mod}\)一个数\(y\)的最小值,可以考虑枚举剩余系,也就是枚举区间\([0,y),[y,2y),[2y,3y)...\)中的最小值(求后缀最小值也一样)更新答案,复 ...
- [CF587F]Duff is Mad[AC自动机+根号分治+分块]
题意 给你 \(n\) 个串 \(s_{1\cdots n}\) ,每次询问给出 \(l,r,k\) ,问在 \(s_{l\cdots r}\) 中出现了多少次 \(s_k\) . \(n,q,\su ...
- CF587F-Duff is Mad【AC自动机,根号分治】
正题 题目链接:https://www.luogu.com.cn/problem/CF587F 题目大意 给出\(n\)个字符串\(s\).\(q\)次询问给出\(l,r,k\)要求输出\(s_{l. ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- Codeforces 1039D You Are Given a Tree [根号分治,整体二分,贪心]
洛谷 Codeforces 根号分治真是妙啊. 思路 考虑对于单独的一个\(k\)如何计算答案. 与"赛道修建"非常相似,但那题要求边,这题要求点,所以更加简单. 在每一个点贪心地 ...
- CF1039E Summer Oenothera Exhibition 贪心、根号分治、倍增、ST表
传送门 感谢这一篇博客的指导(Orzwxh) $PS$:默认数组下标为$1$到$N$ 首先很明显的贪心:每一次都选择尽可能长的区间 不妨设$d_i$表示在取当前$K$的情况下,左端点为$i$的所有满足 ...
- CF1039E Summer Oenothera Exhibition 根号分治,LCT,ST表
CF1039E Summer Oenothera Exhibition LG传送门 根号分治好题. 可以先看我的根号分治总结. 题意就是给出长度为\(n\)的区间和\(q\)组询问以及一个\(w\), ...
随机推荐
- 小学生都看得懂的C语言入门(4): 数组与函数
// 之前判断素数, 只需要到sqrt(x)即可,//更加简单的, 判断能够比已知的小于x的素数整除, 运行更快 #include <stdio.h> // 之前判断素数, 只需要到sqr ...
- cf1121d 尺取
尺取,写起来有点麻烦 枚举左端点,然后找到右端点,,使得区间[l,r]里各种颜色花朵的数量满足b数组中各种花朵的数量,然后再judge区间[l,r]截取出后能否可以供剩下的n-1个人做花环 /* 给定 ...
- 用来表达更复杂的sql语句!!!!!extra 原声sql
extra 用来表达更复杂的sql语句!!!!! extra可以指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,但是你至少要使用一个!要注意这些额外 ...
- Python练习题
内置函数 # 5.随意写一个20行以上的文件# 运行程序,先将内容读到内存中,用列表存储.# 接收用户输入页码,每页5条,仅输出当页的内容 def user_check(filename,num=5) ...
- python字符串之split
函数:split() Python中有split()和os.path.split()两个函数,具体作用如下:split():拆分字符串.通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(lis ...
- Caused by: java.net.ConnectException: Connection refused/Caused by: java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
1.使用sqoop技术将mysql的数据导入到Hive出现的错误如下所示: 第一次使用命令如下所示: [hadoop@slaver1 sqoop--cdh5.3.6]$ bin/sqoop impor ...
- 5336: [TJOI2018]party
题解: 比较水啦..dp套dp f[i][j][k]表示枚举了前i位,最大公共子序列匹配状态为j,noi匹配到了第k位 因为g[j]和g[j+1]最多差1 所以可以状压成j 然后内层再dp一下搞出下一 ...
- 【BZOJ3514】Codechef MARCH14 GERALD07加强版 LCT+主席树
题解: 还是比较简单的 首先我们的思路是 确定起点 然后之后贪心的选择边(也就是越靠前越希望选) 我们发现我们只需要将起点从后向前枚举 然后用lct维护连通性 因为强制在线,所以用主席树记录状态就可以 ...
- 【Arduino】Arduino接收字符串
[Arduino]Arduino接收字符串 相关文章 [Arduino]开发入门[十]Arduino蓝牙模块与Android实现通信 在[Arduino]开发入门[十]Arduino蓝牙模块与Andr ...
- Python_os模块
os模块:可以处理文件和目录,是Python系统和操作系统进行交互的一个接口 os模块常用方法: os.getcwd(): 获取当前工作目录,(即当前Python脚本工作的目录路径) os.chdir ...