Noip2018联训日记

版权声明:本文为博主原创文章,随便转载 https://blog.csdn.net/vanillayi/article/details/83146799

莫当繁星,皆挂苍穹

10月16日

subsets

map+vector枚举每个子集, O ( 2 n ) O(2^{n}) O ( 2 2 n ) O(2^{2n}) ,80分

折半枚举,左边 3 n / 2 3^{n/2} 枚举不选/第一组/第二组,然后计算第二组减第一组的差 x x ,map离散化 x x y y ,将它们的的并存在 v e c t o r [ y ] vector[y] 中,后半段也如此 3 n / 2 3^{n/2} 枚举,与 v e c t o r [ m a p [ x ] ] vector[map[x]] 中所有值取并,并打上标记,最后 2 n 2^n 检查标记,由于map里每个差最多来自 2 n / 2 2^{n/2} 对,复杂度最坏为 O ( 6 n / 2 ) O(6^{n/2})

swap

记忆化搜索, O ( n 3 ) O(n^{3}) ,70分

有任意一个点的位置不变直接无解,否则就可以推断出一个数如何移动,以及在移动它的时候所需的方案的先后关系,若先后关系有矛盾也无解,不然问题就可以转化为一个大小为n-1的排列,某些地方限定了相邻两数的大小关系,求方案数,直接简单DP即可, f [ i ] [ j ] f[i][j] 表示前 i i 个数,第 i i 个数在前 i i 个数中是第 j j 小的,前缀和优化, O ( n 2 ) O(n^{2})

moiezen

枚举 x x 再二分, O ( m i n ( n , p ) l o g ( n p ) ) O(min(n,p)log(np)) ,50分

每次加上的 x x 一定是一个 p a [ i ] p-a[i] 才最优,可以存下来然后去重,加上一个随机化,在枚举x的时候先去检查一下是否比目前的最优解要优,是才继续二分,由于一个随机排列中比前面所有数都大的数的数量期望为 l o g log ,所以复杂度为 O ( n p + n l o g ( n ) l o g ( p ) ) O(np+nlog(n)log(p))

10月17日

dream

HK算法跑二分图匹配, O ( n 2 n ) O(n^{2}\sqrt{n}) ,70分

将点从小到大排序,线段按左端点从小到大排序,维护一个可重集,枚举每个点,将左端点小于其的线段的右端点全部加入可重集,将比它小的右端点全部删掉,然后选取最近的右端点, O ( n l o g ( n ) ) O(nlog(n))

toy

DFS,枚举每个球接在哪一个上面, O ( n ! ) O(n!)​ ,30分

DP, f [ i ] [ j ] f[i][j] 表示一棵 i i 个结点的带标号树深度不超过 j j 的方案数, g [ i ] [ j ] g[i][j] 表示一个 i i 个结点的带标号森林深度不超过 j j 的方案数

一个森林所有树的顶端连起来就是一棵新的树,并且深度增加1,即 f [ i ] [ j ] = g [ i 1 ] [ j 1 ] f[i][j]=g[i-1][j-1]

一个森林加上一棵树还是一个森林,枚举最后面添加的树的大小k,注意到直接转移会造成重复,所以每次转移的时候要保证最小的点在新加入的树里面,即硬点一个点, g [ i ] [ j ] = k = 1 i g [ i k ] [ j ] f [ k ] [ j ] C ( i 1 , k 1 ) g[i][j]=\sum_{k=1}^{i}g[i-k][j]*f[k][j]*C(i-1,k-1)

A n s = ( i = 1 n 1 ( f [ n ] [ i ] f [ n ] [ i 1 ] ) i ) / ( n 1 ) ! Ans=(\sum_{i=1}^{n-1}(f[n][i]-f[n][i-1])*i)/(n-1)! O ( n 2 ) O(n^2)

icekingdom

每次询问扫一遍, O ( n 2 ) O(n^2) ,50分

每次询问 [ l , r ] [l,r] 时,若其中一条边都没有,那么就会有 r l + 1 r-l+1 个联通块,每当有一条边连接的两个点在 [ l , r ] [l,r] 之间,就会减少一个联通块,所以每次询问答案为 r l + 1 ( [ l , r ] ) r-l+1-(俩端点在[l,r]之间的边的数量) ,可以离线下来用树状数组,也可以在线可持久化线段树, O ( q l o g ( n ) ) O(qlog(n))

10月18日

cdq

CDQ分治, O ( n l o g 2 n ) O(nlog^2n) ,36分

分别以 a b / a c / b c ab/ac/bc 求三次二维偏序并全部加起来,这个可以随便做,对于每一对 ( i , j ) (i,j) ,称 i i 大于 j j i i 至少在两个维度上大于 j j ,比如( a [ i ] > a [ j ] a[i]>a[j] b [ i ] > b [ j ] b[i]>b[j] c [ i ] < c [ j ] c[i]<c[j] )或( a [ i ] > a [ j ] a[i]>a[j] b [ i ] > b [ j ] b[i]>b[j] 且> c [ i ] > c [ j ] c[i]>c[j] ),前者在计算二维偏序时会被算一遍,后者在计算二维偏序时会被算三遍,且它们的和为 C ( n , 2 ) C(n,2) ,我们要计算后者的数量,所以 A n s = ( p x ( a , b ) + p x ( a , c ) + p x ( b , c ) C ( n , 2 ) ) / 2 Ans=(px(a,b)+px(a,c)+px(b,c)-C(n,2))/2 O ( n l o g ( n ) ) O(nlog(n))

来源

easy

暴力枚举选哪些数, O ( q 2 n ) O(q2^n) ,15分

先将 [ g , l ] [g,l] 里是 g g 的倍数又是 l l 的约数的数处理处理,不超过800个,最多8个质因数(后文一直假设有8个质因数)

选出的集合里的数必须满足每个质因数出现次数大于 g g​ 小于 l l​ ,且至少有一个顶上界/抵下界,所以状压DP, f [ i ] [ j ] f[i][j]​ 表示选到第 i i​ 个,质因数顶上界的状态和抵下届的状态为 j ( 0 j < 2 16 ) j(0\leq j<2^{16})​ 的方案数,枚举每个 i i​ j j​ 以及是否选择这个数来转移

现在要硬点某个数 i i 必须选,可以正着一遍DP再反着DP ( f 2 [ i ] [ j ] ) (f2[i][j]) ,计算不包含 i i 时的方案数,枚举 i i 前面的状态 j j ,其贡献为 k = 0 2 16 [ j   o r   k = 2 16 ] f [ i 1 ] [ j ] f 2 [ i + 1 ] [ k ] \sum_{k=0}^{2^{16}}[j \ or \ k=2^{16}]f[i-1][j]*f2[i+1][k] ,于是就可以可以 O ( 1 ) O(1) 回答,总复杂度 O ( A c c e p t ) O(Accept)

来源or代码

hard

无输出, O ( 1 ) O(1) ,0分

不会,可参考官方题解

10月19日

错误整理

淡看人间,森罗万象

猜你喜欢

转载自blog.csdn.net/vanillayi/article/details/83146799