QAQ 从IOI搬了一道题目过来
官方题解貌似理论上没有我的做法优,我交到BZOJ上也跑的飞快
结果自己造了个数据把自己卡成了4s多,真是忧桑的故事
不过貌似原题是交互题,并不能离线
说说我的做法吧
首先我们会写暴力,而我的做法只要会写暴力就可以了
对于一个询问A,B
我们有以下几种方法:
1、搞出所有颜色是A的DFS序对应区间的左右端点和所有颜色是B的DFS序对应区间的左右端点
然后把所有端点排个序,线性扫一遍,维护一个扫描线cnt,当遇到A的左端点时++cnt,遇到A的右端点时--cnt
遇到B的左端点时ans+=cnt,这样我们就可以统计答案了
我们可以预处理出所有颜色的DFS序分别排序后的结果,每次做的时候归并排序一下就可以了
时间复杂度O(S(A)+S(B)) 即A颜色的个数+B颜色的个数,空间复杂度O(n)
2、我们DFS整棵树,记录上面DFS的时候经过了多少个A,经过B的时候更新答案就可以了
时间复杂度O(n),但是如果我们开O(n)的空间就可以在固定A的情况下求出所有可能的B的答案了
我们有如下两种做法之后就自然而然的可以A掉这道题目了
首先对于大小大于sqrt(n)的颜色,我们会发现它最多有sqrt(n)个,然后我们对于每个颜色DFS一遍计算答案
时间复杂度O(n*sqrt(n))
对于大小小于sqrt(n)的颜色,我们采用第一种做法
时间复杂度O(n*sqrt(n))
所以总时间复杂度O(n*sqrt(n))
注意到本题出题人热衷于卡内存,但是允许离线
所以不能预处理sqrt(n)个颜色的答案,只能将询问排序之后做
又注意到当A颜色>sqrt(n)或者B颜色>sqrt(n)的时候DFS的方式是不同的
但都是普及组的内容,随便写写就好啦,归并排序也是普及组的内容
所以代码还是极其好写的