CSP-S 模拟52
rank10
T1 平均数
二分答案,让所有的数减去这个答案,求前缀和,
然后验证子序列平均数比这个答案小的的个数是否等于K
只需要找前缀和的逆序对个数即可(归并排序)
T2 涂色游戏
70分算法 Dp转移,先考虑对于确定的j个颜色,然后涂上一列的方案数
设g[i][j] 表示涂了i个格子j个颜色有多少方案数,
因为对于确定的j个颜色方案数不好求,于是用 $ g[i][j]=g[i-1][j]*j+g[i-1][j-1]*(p-(j-1)) $求出从p种颜色中选出j种并放满i个格子的方案数
最后乘上 C[p][j]的逆元求出上述dp的意义下的g[n][j]
设f[i][j]表示第i列放确定的j个颜色且满足前i列不单调的方案数,枚举上一列放了k个颜色 ,枚举k与j的交集u
那么 dp转移式
$ f[i][j]=(\sum\limits_{k=max(q-j,1)}^{min(n,p)}f[i-1][k]*\sum\limits_{u=0}^{min(k-(q-j),j)}(C[j][u]*C[p-j][k-u]))*g[n][j] $
注意 第i列的j个颜色是确定的,而前i-1列的颜色是不一定的
特别的 f[1][j]=g[n][j]
最后统计第m列时 $ans=\sum f[m][j]*C[p][j] $
100%算法就是把那一堆转移的参数预处理一下,然后矩阵快速幂就可以了
T3 序列
可持久化线段树
序列上的每一个点开一个线段树记录有多少个询问区间包含该点且记录询问的x值,所以以x为线段树下标,记录询问x的区间且包含该点的个数
因为一个点的线段树和他前一个的差不太多,继承一下上一个点的并插入一些新点,
例如有100个询问区间都包含3,4点,那么4的线段树与3的应该是一样的
具体做法就是开一个vector 记录该点需要进行的操作
对于一个询问不小于z的值的区间[l,r],应在l的线段树里的z位置+1,r+1的线段树的z位置-1,
对于[l+1,r]因为继承关系会继承此信息,而r+1以后的点因为r+1处删去了所以不会包含此信息
可持久化~
查询时对于一个点的,查这个线段树里询问值小于等于点权的询问个数就是对答案的贡献
每次修改时,查询原点权对于答案的贡献并减去,再加上修改后的点权对答案的贡献即可
复杂度分析(分析不对请指出^-^):
时间复杂度:插一个点O(logN) 总共有2*m 次插入操作(+1和-1),所以建树操作为O(mlogN)
第一次答案查询为O(NlogN),以后q次询问共为 O(2qlogN)
空间复杂度:插入一个点建 logN=17个新点,共插入2*m最多200000个点,大概有3e6多,空间完全没问题