码迷,mamicode.com
首页 > 其他好文 > 详细

模拟测试20191027

时间:2019-10-27 10:48:58      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:font   技术   span   两种   class   img   bcb   family   deepin   

$T1:666$

开始以为是数学

打了个表发现步数不超过$50$

直接模拟就好了诶

枚举步数,每次扫所有点尽量往后走就好了

 

$T2:123567$

考场$40pts$后就失去梦想了啊

正解是大神杜教筛(%%%大神$DeepinC$

先看$40pts$的柿子

$$\sum_{i=1}^{\sqrt n}\mu_{i} \times \frac{n}{i\times i}$$

看后边这个$\frac{n}{i\times i}$,是不是和某些东西有点像?

没错,除法分块!

可以发现$1e18$在这样的除法分块下只有约$188$万种取值

$\mu$ 可以直接杜教筛求前缀和

技术图片
1 for(ll i=1,j;i*i<=n;i=j+1){
2     j=sqrt(n/(n/i/i));
3     ans+=(n/i/i)*(S(j)-S(i-1));
4 }
除法分块

 

T3:椎

考场$YY$一棵$Treap$然而暴毙了

正解线段树维护单调栈

我们考虑大根堆$Treap$的结构

1,如果把所有点按照$key$排序的话,他们的$lca$就是他们之间$val$最大的点

2,一个点$i$的深度就是 $从左维护单调栈到i时栈内数的个数+从右开始维护单调栈到i时栈内数的个数-1$

用线段树维护单调栈就可以了

怎么维护?

考虑$solve(l,r,v)$表示把$v$放入区间$[l,r]$的单调栈内后的单调栈

既然是线段树,那主要难点在于怎么合并两个区间

现在我们以左边为例分两种情况考虑

$1,[l,r]\subseteq 当前查询区间$

(1) 插入值$\geq$右区间最大值

  直接递归查询左边,即调用$solve(l,mid,v)$,因为右边一定都被弹出

(2) 插入值$<$右区间最大值

  先递归查询右边,即调用$solve(mid+1,r,v)$,然后把右边最大值插入并递归查询左边,即调用$solve(l,mid,max_{rc})$

  后面的操作维护的就是把右边插入左边后左边剩余个数

$2,[l,r]\cap 当前查询区间$

优先查询右边,即调用$solve(mid+1,r,v)$,同时用一个全局变量维护已经查询过的区间的最大值$lst$_$max$

然后如果$[l,mid]\cap 当前查询区间$ 把现在这个最大值扔到左区间查询,即调用$solve(l,mid,lst$_$max)$

最后就得到了$solve(l,r,v)$

但是这样复杂度不对,因为情况1有可能扫了整个被查询区间,复杂度退化成了$O(n^{2})$

然而我们发现1(2)情况中调用的$solve(l,mid,max_{rc})$和v无关

那么我们可以在插入一个数时把这玩意预处理出来

复杂度$O(nlog^{2}n)$

模拟测试20191027

标签:font   技术   span   两种   class   img   bcb   family   deepin   

原文地址:https://www.cnblogs.com/mikufun-hzoi-cpp/p/11746698.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!