【LOJ】#2497. 「PA 2017」Banany】的更多相关文章

题解 一眼就是线段树维护点分树的dfs序嘛 代码debug一年(手动再见) 码力直线下降,坐等滚粗= = 很明显的我们需要一个点分树,然后求出以每个重心为根的树的dfs序,线段树维护一下每个点的价值-每个点到根的距离 对于修改点直接单点修改,对于边相当于修改了一个子树到根的距离,就是dfs序上一段区间的加减 然后查询点分树里除掉这个点所在子树的区间,查询两边区间的最大值即可 代码 #include <iostream> #include <algorithm> #include &…
题解 看了一眼觉得是求出图对图统计完美匹配的个数(可能之前做过这样模拟题弃疗了,一直心怀恐惧... 然后说是统计一下每种匹配出现的概率,也就是,当前左边点匹配状态为S,右边点匹配状态为T,每种匹配出现的概率的总和作为\(f[S][T]\),我们需要的就是\(f[2^{n} - 1][2^{n} - 1]\) 然而,会发现转移起来似乎非常麻烦,例如,假如两条边一起出现,各自匹配出现的概率是多少? 我们把每组边拆开,变成每条边在匹配中有50%概率出现,一组边同时在匹配中出现的概率是25%,如果t =…
题解 我们发现,题目告诉我们这个东西就是一个lct 首先,如果只有3,问题就非常简单了,我们算出所有a的总和,所有b的总和就好了 要是1和2也是多项式就好了--其实可以!也就是下面泰勒展开的用处,我们可以用一个多项式取逼近这个函数,而且,多项式次数越高越准确,我们大概到13次多项式就好了 如何创造出这个多项式呢,泰勒展开的式子是这样的 \(\sum_{i = 0}^{n} \frac{f^{(i)}(x_{0}) (x - x_{0})^{i}}{i!}\) 其中\(f^{(i)}(x)\)表示…
LOJ#3088. 「GXOI / GZOI2019」旧词 不懂啊5e4感觉有点小 就是离线询问,在每个x上挂上y的询问 然后树剖,每个节点维护轻儿子中已经被加入的点的个数个数乘上\(dep[u]^{k}\) 新加一个点进去只会经过\(\log n\)条轻边只会更新\(\log n\)个节点 然后再维护一下每个子树里被加入点的个数,每次查询一段重链的链尾要加上重儿子个数减去从y来的那个轻儿子的子树个数乘上\(dep[u]^k\) #include <bits/stdc++.h> #define…
LOJ#3087. 「GXOI / GZOI2019」旅行者 正着求一遍dij,反着求一遍,然后枚举每条边,从u到v,如果到u最近的点和v能到的最近的点不同,那么可以更新答案 没了 #include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar('…
LOJ#3086. 「GXOI / GZOI2019」逼死强迫症 这个就是设状态为\(S,j\)表示轮廓线为\(S\),然后用的1×1个数为j 列出矩阵转移 这样会算重两个边相邻的,只要算出斐波那契数然后乘上N就是不合法的方案 #include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #…
LOJ#3085. 「GXOI / GZOI2019」特技飞行 这显然是两道题,求\(C\)是一个曼哈顿转切比雪夫后的线段树扫描线 求\(AB\),对向交换最大化和擦身而过最大化一定分别为最大值和最小值 对向交换最大化是每个点都对向交换 擦身而过最大化需要对向交换最小化,我们一次对向交换相当于交换任意两个数,所以就是每个置换圈的点数-1累加即可 #include <bits/stdc++.h> #define fi first #define se second #define pii pai…
LOJ#3083. 「GXOI / GZOI2019」与或和 显然是先拆位,AND的答案是所有数字为1的子矩阵的个数 OR是所有的子矩阵个数减去所有数字为0的子矩阵的个数 子矩阵怎么求可以记录每个位置能向上延伸的高度\(h[i][j]\) 枚举左下角的端点,用一个单调栈维护即可 #include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_p…
题解 有意思的一个dp,我们对G计数,发现如果不在同一条对角线上的G肯定不会互相影响,所以我们对于每一条对角线dp dp的方式是枚举这个G以什么方式放,横着还是竖着,还是不放 代码 #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cmath> #include <cstring> #include <ma…
题解 首先求一个最短路图出来,最短路图就是这条边在最短路上就保留,否则就不保留,注意最短路图是一个有向图,一条边被保留的条件是 dis(S,u) + val(u,v) = dis(v,T)我们需要求两遍最短路 然后我们发现就相当于在最短路图上走一段,然后走一段非0的部分 我们把旧图保留,在上面连一些边权为0的有向边,从U到V求一遍最短路,由于最短路图是有向的,我们再从V到U求一遍最短路 然而--WA了? 我们发现我们最短路图上下来之后,可能会又走到最短路图上,但是同时选中两条路径是不可能的,我们…
题解 没啥特别好的算法,是个讨论题,由于0 1 ?三类数位中最少的不会超过6 如果1不超过6,那么记录\(f1(S)\)为 \(\sum_{T \subset S} val(T)\)这个可以通过类似FMT的递推式在\(L 2^L\)求出 然后容斥,如果这个数和1的个数差别是偶数就加上否则就减掉 如果0不超过6,记录\(f0(S)\)为 \(\sum_{T \supset S} val(T)\) 然后容斥,如果这个数有偶数个1就加上否则减掉 问号很少的话就是直接枚举计算值了 复杂度\(O(2^{\…
题面 题解 第\(i\)个数之前的符号是或那么记为0,是与就记为1,得到一个二进数x 然后按位分开考虑,如果这一行是1那么记为1,如果这一位数位0记为0,得到一个二进制数\(b_i\) 第\(N\)行是最高位,如果这一位是1的话,需要有\(x < b_i\) 然后我们把所有\(b_i\)从大到小排个序,对于一个\(r\)要满足按照\(b\)的顺序所有的0不在1的前面,然后找到第一个0出现的\(b_i\),最后一个1出现的\(b_j\),答案是\(b_j - b_i\) 代码 #include <…
题面 题解 考虑我肯定是从一个人出发,开始依次标记,而不会跳过某个人,因为如果我跳过了,那么我之后回来还需要标记它,比不上我等完它再一直走到最后(因为多了走一圈之后走回它的代价) 我们倍长整个序列,我们要求的就是 \(Min_{i = 1}^{n}{Max_{j = i}^{i + n - 1}{T_j - j + i + N - 1}}\) 显然\(j\)越大这个值越小,那么又可以转化成 \(Min_{i = 1}^{n}{Max_{j = i}^{2n}{T_j - j + i + N -…
题面 还有这么诚实的出题人! 我们最多影响20个点,然后把这20个点的虚树建出来,并且枚举每个点的选举状态,如果一个点选或不选可以通过改\(dp[u][0] = 0\)或\(dp[u][1] = 0\)完成 状态应该不多,因为每条边只有三种选的情况,上限是\(3^{m - n + 1}\)的 然后我们考虑递推出\(dp[u][0]\)和\(dp[u][1]\)在更新它虚树上的父亲的方案数,是可以用\(k_0 * dp[u][0] + k_1 * dp[u][1]\)表示的,这个可以递推出来 然后…
题解 把没有门的点缩成一个点 如果\(i->i + 1\)的钥匙大于\(i\),那么\(i\)不可以到\(i + 1\),连一条\(i\)到\(i + 1\)的边 如果\(i->i + 1\)的钥匙小于\(i\),那么\(i + 1\)不可以到\(i\),连一条\(i + 1\)到\(i\)的边 按照拓扑序计算,每次暴力向左和向右扩张,每次扩张碰到的区间和当前这个点扩张的区间没有重叠的部分,于是复杂度就相当于把一条链相邻两个点一个个合并起来,是\(O(n)\)的 代码 #include <…
题解 虽然要求一个dfs序,但是不是从根开始贪心 从最小的点开始贪心,最小的点显然是父亲选了之后马上就选它 那么我们每次把最小的点和父亲合并,两个联通块之间也是如此 对于两个联通块,他们合并的顺序应该是平均值较小的更靠前 因为有两个联通块和为\(S_i\)和\(S_j\),大小为\(B_i\)和\(B_j\) 如果\(S_i * B_j < S_j * B_i\)即\(i\)应该放在\(j\)前面,我们可以得到 \(\frac{S_i}{B_i} = \frac{S_j}{B_j}\) 代码 #…
题解 读题是做题关键 我们设\(dp[u][l][r]\)表示\(u\)节点上方没改\(l\)条公路和\(r\)条铁路 然后记忆化搜索,枚举这条点改左边还是右边 代码 #include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #de…
题解 我们冷静一下,先画一棵后缀树 然后发现我们要给c和d这一段区间在[a,b]这一段开头的串里找lcp 而lcp呢,就是c点的祖先的到根的一段,假如这个祖先的子树里有[a,b - dis[u] + 1],那么这个u就是合法的,维护每个点子树里出现过的后缀串起点可以用线段树合并 (这里的深度指后缀树上该点到根的距离) 我们先用min(b - a + 1,c - d + 1)限制一下这个祖先的深度,选择距离根深度最近且深度>= min(b - a + 1,c - d + 1),找的这个点称为p 那…
题解 我并不会做,我觉得很像网络流但是毫无建图思路 我猜了个贪心,写了一下--啥过了90分?!这数据是有多水啊.. 哦又是行列拆点 不过要按照'#'进行拆点,也就是一段横着的区间只能放一个炸弹,一段竖着的区间只能放一个炸弹,如果两个区间的交点是一个空格的话,那么就把这两个区间拆出来的点连边 最后我们只要求一下最大匹配就可以了 代码 #include <bits/stdc++.h> #define enter putchar('\n') #define space putchar(' ') #d…
题解 这个我们处理出来每一位能变化到的最大值和最小值,包括自身 然后我们发现 \(f[i] = max(f[i],f[j] + 1) (mx[j] <= a[i] && a[j] <= mi[i])\) 喜闻乐见的三维偏序转移法 还写树套树??? 直接CDQ分治就好啦 为啥他们的代码就1.xK?????? 我就3.1K 代码 #include <bits/stdc++.h> #define enter putchar('\n') #define space putc…
题解 看错题了,我以为是询问Q是个数字,问它在哪个位置 我一想这不直接01序列搞一下就好了嘛(事实上是012) 然后呢,我发现样例没过. 啊我看错题了,问的是Q这个位置是啥-- 哦,套用我之前的想法不是直接拿线段树维护01序列然后二分吗--(可以不用012,直接是0表示小于等于mid的值,1表示大于mid的值) 哎我要是没看错题这题我是不是做不出来啊 代码 #include <bits/stdc++.h> #define enter putchar('\n') #define space pu…
题解 一写过一交A的水题 只要求一个dfs序,新加一个标记在子树所在的区间上覆盖上该点,维护深度最大的答案 代码 #include <bits/stdc++.h> #define enter putchar('\n') #define space putchar(' ') #define pii pair<int,int> #define fi first #define se second #define MAXN 100005 #define pb push_back #def…
题解 用\(f[i][j]\)表示考虑了前i个排名有j个人被碾压 \(f[i][j] = f[i - 1][k] \* C[k][j] \* C[N - k - 1][N - r[i] - j] \* P[i]\) P[i]是成绩排列的方式,意义是在前面k个人里选了j个来碾压,并将人数空缺用上一次没有碾压的来填补 \(P[i]\)怎么求,对于一个i,考虑枚举B君的成绩,也就是 \(\sum_{j = 1}^{u_{i}} j^{N - r[i]}(u_{i} - j)^{r[i] - 1}\)…
题解 有什么LNOI啊,最后都是JLOI罢了 一道非常--懵逼的统计题 当然是容斥,所有的方案 - 至少有一个点坏掉的正方形 + 至少有两个点坏掉的正方形 - 至少有三个点坏掉的正方形 + 至少有四个点坏掉的正方形 总共的方案就是 \(\sum_{i}^{min(n,m)}i \* (n - i + 1) \* (m - i + 1)\) 至少有一个点坏掉的怎么统计,我们考虑这个点在底边,左边有l个坐标右边有r个坐标,上面有h个坐标 设\(z = min(l + r,h)\) 如果高度大于左右两…
题解 童年的回忆! 想当初,这是我考的第一次省选,我当时初二,我什么都不会,然后看着这个东西,是不是能用我一个月前才会的求lca,光这个lca我就调了一个多小时= =,然后整场五个小时,我觉得其他题不可做,一直杠这题的20分,然后...day1爆零了,之后day2手玩提答好像骗了一点,总归是没爆零 那么这个东西是可爱的树dp啦 首先我们考虑m = n(因为大体的代码都需要这个思路吧 我们设\(f[u][d]\)是u这个点不包括u,可以继续往上覆盖d个点最少需要的代价 \(g[u][d]\)是u这…
题解 在trie树上开vector记录一下这个前缀出现次数第一次达到某个值的下标,以及记录一下现在这个前缀有多少个 为什么thusc有那么水的题--是为了防我这种cai ji爆零么= = 代码 #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cmath> #include <cstring> //#define…
题解 神仙dp啊><(也有可能是我菜) 我们发现,想要拿一段区间的话,只和这个区间的最大值和最小值有关系,那么我们考虑,如果一个区间[l,r]我们拿走了一些数后,使它的最小值是a,最大值是b,用于我们每次选择一段区间拿走 这样的话,我们可以设置一个\(f[l][r][a][b]\)如果我们让\([l,r]\)这段区间清空,最后一次操作拿走的区间,最大值是b,最小值是a 然后用\(g[l][r]\)表示全部拿走区间的所有数\([l,r]\)要花费的代价 转移的时候就是枚举最后一次操作 \(g[l…
LOJ3123 60pts 正难则反,熟练转成总方案数减掉每个片段都大于等于s的字典序的方案 按照一般的套路建出kmp上每个点加一个字符的转移边的图(注意这个图开始字母必须是nxt链中下一个相邻的字符最大的一个,不然就字典序比它小了) 然后大力猜结论可能是走m步走出一个环的个数,很容易发现这是不漏的,因为一个串无限重复最后都会走出一个m步的(不一定是简单环的)环 不重的我没证出来,抱着试试看的心态我们写个极其简单的dp,发现它过了-- 100pts 很容易发现每个点要么走到nxt链中下一个相邻字…
第一次有耐心去研究一道题答-- 以前看到题答要么扔要么就水能简单手玩出来的 1 2可以手玩出来,快乐! 4呢发现3 3比较格路,就把3 3都配了,一边带个4的除了4 4都塞满这么放进去,然后把一边带2的两两配起来,然后撒1把这些都填满,最后扔4 4就好了 剩下的可以用玩俄罗斯方块的技巧,枚举一个位置pos,若底边长度是r,找[pos,pos + r - 1]这个区间上最大值最小的一个,如果相同选pos最小的一个,是可以按照奇怪的方法各种排序,随机扰动-- 基本都是这个套路了,非2的测试点可以通过…
LOJ3120 52pts \(N - D >= 2M\)或者\(M = 0\)那么就是\(D^{N}\) 只和数字的奇偶性有关,如果有k个奇数,那么必须满足\(N - k >= 2M\) 所以设\(f[i][j]\)表示第\(i\)个数有\(j\)个奇数的方案数,\(j\cdot f[i][j] \rightarrow f[i + 1][j - 1]\)和\((D - j) \cdot f[i][j] \rightarrow f[i + 1][j + 1]\) 64pts 这个只需要把上面的…