A. string
类似 HEOI2016排序 。
排序这道题因为只询问单点最终答案,二分答案,
将小于和大于等于答案的数分别设为0 1,
用线段树维护0 1的排序即可。
算法一:
本题中的1~n变成了0~25(即a~z),单点询问变成了全体询问。
仿照排序那道题的做法,线段树优化桶排序。
维护每个节点每个字符的cnt值,区间查询后区间赋值即可。
然而up和down函数都是$O(26)$的,加上修改操作最多被拆分为26个,
总的复杂度为$O(nlogn26^2)$。
需要卡常。
考场上码出了80分,一次优化成了70,再一次优化成了60。
考后把第一次拿出来,加了快读,卡到了90。
循环展开AC。
算法二(来自DeepinC):
思路同样来自HEOI2016排序。
枚举i,范围为0~25,把大于i的字符设为1,反之设为0。
对于每个枚举,线段树维护桶排序,执行m次操作。
每两次枚举中,最终01串中由1变为0的,就是字符i。
复杂度$O(nlogn26)$然而好像常数巨大,只能卡到70分左右。
算法三(好像是正解):
用26棵线段树。
每棵线段树只维护0 1, 分别表示等于或不等于该字符。
其他同算法一,
总复杂度也为$O(nlogn26)$。
算法四(来自sdfzdky):
维护线段树的每个节点是否全部相等,
如果是则直接返回区间大小,否则继续递归。
排序过程同算法一。
根据均摊的思想,复杂度是对的。
最差情况下$O(nlogn26)$,然而在随机数据下很优秀。
算法五(来自cbx):
将连续的同一字符区间看作同一个元素。
暴力桶排序。
复杂度似乎也是对的。
B. matrix
考试时打了状压。
正解:
(右侧区间为由右端点m开始的区间,即$[r[i],m]$,左侧区间同理)
定义$f[i][j]$表示考虑前i列,前i列中有j列在右侧区间放1,已经考虑结束端点小于等于i的左侧区间。
状态定义很奇怪,但是是可以转移的。
定义$lp[i]$表示前缀和,$lp[i]$的含义是有多少个左侧区间已经在i点结束。
同理$rp[i]$的含义是i点有多少个右侧区间能放1。
$f[i][j]=f[i-1][j]+f[i-1][j-1]*(r[i]-j+1)$
加号前面的内容表示这个点不在右侧区间放1,
后面的内容表示由可以放1的任何一个右侧区间在这里放1。
转移后,考虑左侧区间。
$f[i][j]*=A_{i-j-l[i-1]}^{l[i]-l[i-1]}$。
$f[m][n]$就是答案。
C. big
考试时打了显然的暴力。
原文地址:https://www.cnblogs.com/skyh/p/11286749.html