7.1模拟赛赛后总结

7.1模拟赛赛后总结

赛时历程

​ 二十分钟浏览题目,感觉今天的三道题应该都有能写的。

​ 然后开始异想天开,打算在十点半之前拿下38+44+17=99分,然后再考虑后边能拿的。

​ 结果T1暴力就写错了点东西,因为我忽略了到自己的dis这个事情,所以一开始是搞错了(然后并没有意识到,并发现找第K大就能过样例一,还在想是不是题面错了)。

​ 然后打后边的十几分的换根DP,结果还整错了一会儿。结果打完T1并对拍完,(顺便发现暴力打错,怪不得那个K小好像得反过来算)就已经是十点多了。

​ 本着能完成多少就多少的思想,我想着先搞定较简单的T3的17分。

​ 还好,除了那个44分,十点半之前搞到了剩下的55分。

​ 然后有点自闭,T2好像很难。这个时候我又困了。

​ 来回看T2T3并懵逼到十一点半,清醒了不少,开始手画T2样例,画完样例感觉有点想法,于是从链做起,找链的结论的时候逐步完善判断状态是否合法的方法,于是十二点半的时候打完链,十二点四十五打完了前边的状压的分数。一开始计划的东西花了两倍時間才完成。

​ 感觉这是最近打的最高的一次了,终于不是那三、五十分了,类目,于是剩下的時間仔细检查了一波(T2差点RE、分段要注意完全分割开,全局应用的一定要开成N)。

赛后发现

​ 并列RK2,还好(比原来rk倒一好多了好吧/kk)。zyz又双叒叕 RK1了。冀队首归好像就会T1正解orz(虽然挂了。。

​ 该拿的都拿到了。虽然因为这场比较简单吧。。去年他们那帮人好多AK的。。

技术总结

T1

​ 想到什么权值线段树是理所当然,期望树高logn也是明明白白,但是并没有想到转化一下求dis的方式。树上求dis可以用 \(dis(i,j)=dep[i]+dep[j]-2*dep[lca(i,j)]\) 这样的方式,发现对于 \(i\) ,只需要找到第 \(K\) 小的\(dep[j]-2*dep[lca(i,j)]\) 即可,这棵树是随机的,所以说只要知道最多 \(logn\) 级父亲的线段树内存放的 \(dep[j]-2*dep[x]\) 即可,所以考虑从上到下dfs,假设现在线段树内有所有\(x\)的子树外的由父亲们fa产生的\(dep[j]-2*dep[fa]\),那么每次将\(x\)自己当lca加入自己子树内的所有 \(dep[j]-2*dpe[x]\) 到线段树内直接查找,暴力扫就行,因为这个树高导致复杂度是逐级递减的,就像点分治一样,然后进入儿子的子树之前要删除掉 \(y\) 内x做父亲的所有 \(dep[j]-2*dep[x]\) ,这样就保证了进入 \(y\) 的时候线段树内只有所有 \(y\) 的子树外的父亲们fa产生的\(dep[j]-2*dep[fa]\),出来的时候两个修改都删掉即可。

T2

​ 先讲暴力,从链上可以知道,如果进行了\(access(x)\),那么会产生一个全1串,这个时候对这个串怎么添0呢?那就是在\(1\)~\(x\) 之间的任意一个点y进行\(access(y)\),这样y到儿子的边就会变成0,为了不重不漏的统计,考虑枚举每次第一个\(access\) 的点,然后在中间选择\(access\)来添0,不过不能对\(fa[x]\) 进行 \(access\),因为这样会到一个第一次就\(access(fa[x])\) 的局面,会算重。然后方案数量就是不access的方案\(1\) 加上access的所有状态\(\sum\limits_{i=0}^{n-2}\sum\limits_{j=0}^{min(K-1,i)}\dbinom{i}{j}\)。然后暴力的话就是把所有的边的状态状压一下,然后判断一下:

  1. 不存在一个点有两个实儿子。
  2. 达成这个状态需要的操作次数不超过K。

操作次数怎么算?发现要达成一个局面的最小操作状态是从下往上来的,而如果下边有一串1,那么每多一个0,就多一次操作次数,统计有1的边(最上边的那个,遇到1或者跳到根停止)往根走的0的个数即可。

​ 然后是AC,精巧,简洁而就是不会。刚刚的暴力提示到操作要从下往上来,那么设计状态\(dp[x][k]\)\(x\) 的子树下 \(access\) k次的状态数量, 然后考虑向上合并的时候,不同子树的状态肯定是乘法原理,但是只能有一个实儿子,所以说考虑是否 \(access(x)\),所以考虑一些辅助数组,设 \(g[x][k]\) 表示向上有实边的方案数,然后每次对于每个儿子进行转移时使用两个temp,一个是tempf,一个是tempg,每次考虑已经处理过的儿子 \(f[x][j]、g[x][j]\) 和当前的儿子 \(f[y][k]、g[y][k]\) ,更新的时候access的次数直接j,k相加,对于\(tempf[x][j+k]\),用 \(f[x][j]*f[y][k]\) 直接更新,对于 \(tempg[x][j+k]\) 它等于 \(f[x][j]*g[y][k]+g[x][j]*f[y][k]\) 表示选择当前y做实儿子或者选择已经遍历过的做实儿子,然后每次将temp复制到 \(f[x],g[x]\) 中,更新好已经遍历过的儿子,最后退出这层之前,要注意把 \(g[x]\) 复制到 \(f[x]\) 当中,因为刚刚考虑的都是儿子如何如何,向上考虑都是下一次DP决定的,刚才的遍历都只和儿子们的操作有关,然后对于 \(f[x][0]\) ,这个要归1,对于 \(f[x][1]\) 这个要-1,-1是因为对于 \(x\) 只操作一次多统计了一次 \(access(x)\) ,向上没有实边的话就不能有这个操作,那么最后实际上 \(f\)\(g\) 差的只是 \(f[x][1]\)\(f[x][0]\) .

T3

​ 还是一个DP。考场上考虑到了每个配对是独立的,或许能够考虑计算答案为每个值的时候的方案数,但并没有朝着DP的方向想。设置状态 \(f_c[i][j]\) 表示某个配对 \(c\) 产生的绝对值为 \(i\) ,异或值为 \(j\) 的方案数,这个还是很好算的,只要枚举二者的取值即可计算出方案,然后将匹配结合起来的时候也可以通过类似的方式,最后统计的时候把方案*贡献累加即可,然后这个是可以在比大小的地方前缀和的,可以做到 \(n^3\) 。考虑换个状态,\(f_c[i][j][0/1]\) 表示某个配对 \(c\) 产生的绝对值为 \(i\) ,第k位异或值为 \(0/1\) 的方案,那么配对之间枚举每一位的取值然后算每一位的方案结合起来,比大小的地方也可以前缀和优化,而这个不用枚举异或可以做到 \(O(n^2logn)\) ,不错的复杂度。发现瓶颈在枚举初始状态的时候,计算\(f_c[abs(i-j)][k][0/1]\) 怎么更快呢?这个用多项式就好啦~(十级不考,战略放弃/kk)

posted @ 2021-07-01 23:04  explorerxx  阅读(35)  评论(0编辑  收藏  举报