HN2018省队集训
HN2018省队集训
Day1
今天的题目来自于雅礼的高二学长\(dy0607\)。
流水账
震惊!穿着该校校服竟然在四大名校畅通无阻?霸主地位已定?
\(7:10\)从校门口出发,坐公交几站就到了雅礼了,一种比我们学校高到了不知道哪里去的既视感。
在门口咕咕咕了半个小时,进了一个比较破旧的机房。
一股我们学校\(4\)机房既视感。然而4机房暑假也要装修了
只有\(Win7\),我忽然觉得今天可能会有点小麻烦了。
还是好好看题为妙。
先看\(T1\),一眼感觉像\(LCT\),随手敲了几行,先看看后面的题目。
第二题怪怪的,先跳。
第三题一脸多项式既视感,一眼会\(O(nk^2)\)的\(dp\)。
回去看\(T1\),忽然感觉不需要\(LCT\),可以树链剖分+大力讨论解决。
主要的问题在于怎么在换根之后求\(LCA\),只需要大力讨论一波就可以了。
虽然有\(gdb\),但是在\(Win7\)下不太会用,调了两个小时才写过打样例,\(Dev\)的调试太不舒服了。
然后看\(T2\),画下图,发现就是在一个梯形中找一个最小的元素。
因为同一列的元素可以直接计算,相当于只需要在\(y=1\)上面找就可以,复杂度\(O(nq)\)
发现可以过\(27\)分。
看\(T3\),直接写出来\(O(nk^2)\)的\(dp\),这个东西就是\(46\)分。
接着发现每次转移都是一个卷积,用\(NTT\)做就好了,时间复杂度\(O(nklogk)\),这样有\(59\)分。
再回头看\(T2\),发现有随机数据,再看看上面的式子,发现具有单调性。
所以用一个单调栈维护一下,每次计算的时候只需要跳到下一个比他小的位置计算就好了。
这样就可以有\(42\)分了?
接着想\(T3\),总觉得可以多项式快速幂什么的预处理一下,然后就可以变成\(O(klognlogk)\)
但是思考了很久,发现总是有一个\(2^k\)搞不掉,也没有办法了。
所以,今天的期望得分:\(100+42+59=201\)
然而,实际得分\(62+42+59=163\)
\(T1\)发生了什么呢?我明明都开了$long\ long $了啊。
打开程序,发现我在放置标记的时候没有开\(long\ long\),而我下放标记就是用放置标记写的。
导致有两个\(SubTask\)错了点,从而少了分。
简答的题解
T1.Tree
题意
给你一棵树,有三个操作
换根,把两点的\(lca\)的子树点权全部加上\(w\),询问某个点的子树权值和。
题解
先拿\(1\)当做根进行树链剖分。以下的子树,\(lca\)都是相对于以\(1\)为根而言。
考虑换根后怎么求两点的\(lca\),如果一个点在根的子树内另外一个点在子树外,那么\(lca\)就是根。
否则,先求出两点在以\(1\)为根的树中的\(lca\),记两点\(u,v\),\(lca\)为\(x\)
如果根在不在\(x\)的子树中,显然需要的\(lca\)就是\(x\)
否则,就是沿着根向上跳,与\(u-lca-v\)路径的交点。
这个对\((x,u)\)和\((x,v)\)求\(LCA\)就可以判断。
至于一个点在当前根下的子树,还是分根在当前点子树内还是当前点子树外考虑。
如果在当前点\(u\)子树内的话,设根到\(u\)的路径上,最靠近\(u\)的点是\(v\)
这样子在当前根下\(u\)的子树就是整棵树除去\(v\)的子树。
否则在当前点的子树外,则子树就是以\(1\)为根时的子树。
这样子分类讨论一下就好了。
T2.Function
题意
有一个\(10^9\times n\)的网格,每一列的格子都拥有相同的点权,每次可以向上或左上走一次,直到最上面那行。
求路径上格子点权和的最小值。
题解
首先,无论那种走法,一定等价于先向左上走一段,再一直向上。
所以我们可以一个\(O(nq)\)的暴力,设当前询问点\((x,y)\)
我们向左走到\(i\),那么贡献就是\(s[y]-s[i]+A[i]\times (x-y+i)\)
考虑一下对于任意\((x,y)\),我们把贡献拆成三个部分来看。
第一部分:\(s[y]\),定值,对结果没有任何影响。
第二部分:\(A[i]\times i-s[i]\),只与\(i\)有关的式子,与询问无关,也是定值。
第三部分:\(A[i]\times (x-y)\),与询问有关。
我们先往回考虑暴力,我们从大往小枚举\(i\),那么如果当前的\(i\)比之前的那个更优
一定满足\(a_i\)单调,否则一定不会更优。
所以对于本题纯随机的数据,可以用单调栈提前预处理,这样子只需要跳第一个比他小的位置就好了。
那么回归上面的贡献的三个部分。
我们发现第一和第二部分是不变的,因此只需要考虑第三部分。
第三部分直接考虑显然就变成了暴力,我们考虑把所有的询问一起考虑。
我们按照\(y\)排个序,这样子的话,选择每个点的作为最优值的情况都是一段连续的\(x\)。
既然按照了\(y\)排序,所以我们顺次插入所有的\(a_i\),用一个单调栈维护一下每个点掌握的\(x\)的区间。
每次新插入点的时候,考虑当前点会不会比栈顶的点更优,如果更优就直接弹出去。
然后考虑如何计算这个点掌握的\(x\)轴的范围,这个二分一下就好了。
然后如何计算答案,显然在栈内二分一下,看看这个询问的\(x\)应该从哪个点转移过来就好了。
T3.Or
题意
有\(n\)个数\(a_i\),每个数的范围都是\([1,2^k]\),设\(a_i\)的\(or\)前缀和\(b_i\)
即\(b_i=a_1\ or\ a_2\ or\ ...\ or\ a_i\),要求\(b\)单调递增,求满足条件的数列\(a\)的个数。
题解
考虑一下\(dp\),设\(f[i][j]\)表示前\(i\)个数用了\(j\)个二进制位的方案数
最后的时候再额外乘一下\(C_K^j\)就好了。
我们发现这是一个卷积形式,令\(F_i(x)\)为\(f[i][j]/j!\)的指数型生成函数
那么,$$F_i(x)=F_{i-1}(2x)\times(e^x-1)$$
每一步都只需要考虑后面那一部分,剩下的递归计算一下。
我们发现$$F_n(x)=\prod_{i=0}{n-1}(e-1)$$
考虑如何快速计算后面的累乘式,我们利用倍增来计算。
如果\(n\)是偶数,我们分成前后两半,设前一半为\(G(x)\),那么后一半为\(G(2^{n/2-1}x)\)
如果是奇数,则把多出来的那一项直接乘到答案里面去,然后剩下的继续处理。
然后前后两半乘起来就好了。时间复杂度\(O(klognlogk)\)
总结
今天的题目难度并没有想象中的大,并且部分分也是相当的好拿,今天的暴力写满应该就是\(100+42+59=201\)吧。可是我却没有拿满。
还是写题目的时候的一些小错误导致了丢分,以后无论写什么,写完之后思考一下数据范围,如果存在取模或者要用\(long\ long\),一定要好好的检查一下是否都用了\(long\ long\),或者是否都取好了模。
要像\(HNOI\)的时候的那种状态,什么题目都好好想清楚,一定不能落下任何细节,做到不犯任何错误,做题目也要小心翼翼,不要一下子直接打了一堆东西出来,结果调都给调死,浪费一堆的时间。
Day2
今天的题目来自于\(laofu\),laofudasuanbaofushehui
今天的题面有彩蛋。(雾
流水账
在校门口买了点东西吃,碰到了\(xzy\),然后发现了\(zsy\),然后一起去公交车站。
等了一下\(dsl\)和\(tjj\),所有人就出发去雅礼了。
今天没咕咕咕,去的时候已经有人到了,空调也还不错。
\(8:00\)准时开始考试,看到\(laofu\)的题目瑟瑟发抖,然后果然有一道叫做\(string\)的题目。
先看\(T1\),我会\(O(n^2)\),随手敲完\(T1\)。
再看\(T2\),我们\(O(Tn!)\),等下,\(n\le 5\)直接打表就好,而且样例连表的告诉你了。
再看\(T3\),什么鬼玩意?我会\(O(n^2)\)。啥?\(O(n^2)\)只有\(n=100\)的十分?
下一档分就是\(n\le 10^5\)了?
我似乎会分块的做法,应该可以拿\(40\)分,然而并不会回文树前端插入的姿势,没办法啊。
把暴力全部码完,出去上了个厕所。恩?下雨了。
回去忽然发现\(T2\)如果走不通一定是一条斜线穿过去,并且一定隔断了一个点。
这样子可以暴力枚举割了哪里,然后再容斥一下,这样子\(O(Tn^2)\)。
再前缀和优化一下\(O(Tn)\),再用一次前缀和优化一下,\(O(T)\)。
好的,\(80\)分到手。
忽然注意到代码长度不超过\(100kb\),这不是让我们打表吗?
大力打了一个表,发现极限要跑\(5s\)?
于是把\(80\)分拼起来,然而拼的时候\(gg\)了。。。。
剩下的时间发现\(T1,T3\)都写不动了。。。。
简单的题解
T1.Walk
题意
给定一棵树,每个点有点权。如果一个点的祖先的权值是这个点权值的倍数,
那么可以直接从那个祖先移动过来,问每个点从\(1\)号点过来的方案数。
题解
留坑。
T2.game
题意
有一个\(n\times n\)的方格,在上面放上\(n\)个车,要求车与车时间不能互相攻击。
问在不经过含有车的格子的情况下,\((1,1)\)与\((n,n)\)联通的车的摆放情况的方案数。
题解
对于一个不合法的方案,一定能够找到一个位置\((i,i)\),
使得所有的\((x,i+1-x),x\in[1,i]\)都被车给覆盖。
此时的方案数就是剩下的\((n-i)!\)。
同样的,跨过方格的主对角线的方案是对称的。
那么这样子减去所有不合法的方案,发现就是一个阶乘的前缀和。
再容斥减去两侧都割开了的方案数,发现是一个阶乘的前缀和的前缀和。
这样子预处理这些东西就可以拿到\(80\)分。
\(10^9\)的数据显然不是常规做法,发现可以分段打表,然后就可以\(AC\)了。
神TM雅礼老爷机跑5s,我会自己机房随便跑0.6s就出来了
T3.string
题意
给定一个串\(S\),若干组询问,每次回答\(S[l..r]\)中本质不同的回文串个数。
题解
我在考场上似乎\(yy\)出一种\(O(n\sqrt n)\)的\(40pts\)在线做法,然而不会回文树前端插入的姿势,只能作罢。
这个想法大概是把原串分块,设\(p[l,r]\)为第\(l\)块到第\(r\)块的回文树,这个节点总数是\(O(n\sqrt n)\)的。
每次询问的时候把被他覆盖的完整的一段已经预处理过的回文树扣出来,
直接在上面前端插入,后端插入,然后回答询问。
因为每次插入最多涉及到新加一个节点、修改一个点的儿子信息。
因为插入操作是\(\sqrt n\)次,所以可以用一个栈之类的东西暴力维护一下修改了哪些地方,
然后撤销这些操作,让回文树回到一开始的状态就好了。
这样子的话均摊复杂度\(O(Q\sqrt n)\)。然而这样子并不是均摊的,可以卡掉。
还是回到正解。
既然不是强制在线,那么我们考虑一下如何离线解决。
我们把所有询问按照\(r\)排序,然后我们依次加入字符,考虑以当前字符为结尾的所有回文串的贡献。
假设当前的串上一次出现的结束位置是\(pos\),这个串的长度为\(len\)
那么,如果某个询问的左端点\(l\)在\(pos-len+1\)之后,
那么,当前新加入的这个串会对于左端点在上述位置之后的所有询问的答案增加一。
但是,在回文树上,一个节点表示的串如果出现,那么它所有的回文后缀也必定会出现。
所以,考虑一下这些回文后缀产生的贡献。
作为当前串的回文后缀,根据对称性,一定是当前串的回文前缀。
所以,它的最后一次出现位置一定在当前串的上一次的出现位置之前。
那么,因为只要长度不跨过\(len/2\),意味着这一系列的串的长度之差是相等的。
所以我们发现他们对于答案产生的贡献是连在一起的。(画个图就知道了)
所以,把他们的贡献连在一起修改就好了。
这样的时间复杂度是\(O(nlog^2n)\)。
这道题目也提供了一个非常好的思路,当计算类似本质不同之类的东西时。
将询问离线,那么,每次插入一个新的位置,考虑它会对哪些左端点所在的询问会产生贡献。
对于这一段加上贡献,有点类似于线段树优化\(dp\)的操作。
总结
明明昨天说了,今天却又犯脑残错误,我也不知道该说什么好了。
今天的题目总体来说不是很良心,部分分给的不是很足,毕竟laofudasuanbaofushehui
\(120+\)是比较标准的部分分,然而我又一次没有拿满,十分蛋疼。
一次次说不再犯傻逼错误,结果一次次又犯,真的是什么鬼玩意啊。
从今天开始,一定,一定,一定不再犯某些傻逼错误了。
Day3
今天的题目来自于一中的三名学长
流水账
今天早上正在纠结去哪里吃早餐,就碰上\(zsy\)了。
早上到的时间大概是\(7:45\)左右。
先看\(T1\),仔细思考了一波,发现自己会一条线段上的做法。
如果把一条线段的做法直接丢到环上,在稍微判断一下能够加进来一条线段,
然后就可以过样例了,水得不行。就暂时没管了。
\(T2\),一眼会\(O(n^4)\)的暴力,然后一眼感觉链是可以做的。
然后开始写\(O(n^4)\),忽然发现可以写到\(O(n^3)\),然后码码码。
然后先写\(T3\),打了个表,看了好久都没找出一点规律,最后时间不是太多了,直接写\(10pts\)滚粗。
回去看\(T1\),自己随手构了一组数据把自己\(Hack\)了。
索性\(rand\ 50\)次,每次\(O(n)check\),对于\(ans\)取\(max\),感觉能过,没管了。
回去写\(T2\)的链,大力推一波式子,但是发现和我的暴力跑少了\(100\)的答案。
后来发现我似乎对于题目的理解有一些偏差,然后改了改就过了。
下午然而发现\(T1\)全部\(RE\)了,回到学校发现是数据水得不行,很多数据都没有横跨线段两端的边。
意味着只需要把一条线段的贪心拿出来就可以随便拿分。
简单的题解
T1.c
题意
有一个环,有\(n\)段圆弧,每段圆弧顺时针从\(l_i\)覆盖到\(r_i\),线段之间端点可以重合。
求能够选择的最大圆弧数。
题解
首先,如果一个圆弧被别的圆弧完全不该,那么他就是没有任何意义的。
排序之后然后用一个栈之类的东西随便搞一下,就可以搞好了。
并且搞好之后,线段的\(r\)一定递增,并且不会互相包含。
现在不考虑圆弧,假设圆弧被断成了线段。
那么这就是一个很显然的贪心,从最左侧的那根线段开始,能够选就选。
为什么这样是对的?假设这根可以选,但是没有选,而选了下一根。
根据上面的结论,\(r_i<r_{i+1}\),那么,当前这一根线段选择之后导致后面的线段不能选的情况一定不会比\(i+1\)差。
所以能选则选。
现在考虑环,唯一的问题是什么呢?
可能会有一条跨越了\(n\)的线段影响到了前面的抉择。
考虑如何暴力?我们显然是选一根横跨\(n\)的线段,然后圆弧就被断开成了线段,贪心即可。
但是横跨\(n\)的线段很多,不能暴力求。
如果数据纯随机,那么随便\(rand\)个几十次,每次\(O(n)\)就好了,基本不会错。
然后这样子你就可以\(AC\)了。
T2.a
题意
给定一棵树,依次选定\(K\)条路径,要求每条边要么被覆盖\(K\)次,要么被覆盖\(1\)次,也可以不覆盖。
求方案数。
题解
考虑一下暴力,我们每次枚举两个点之间的路径作为所有路径的交。
那么,贡献显然由一些点进入这条路径的两个端点的子树构成。
那么,我们可以做一个背包,设\(f[i][j]\)表示在\(i\)的子树中选中了\(j\)个点的方案数,
同时满足所有任意两个点的\(LCA\)都是\(i\)。
那么,每次加入一个儿子的时候,这个点要么选择在这个儿子的子树中,
形成一个只被覆盖了一次的路径。或者选在这个点上面,形成一条只经过所有路径交的路径。
那么,两个点之间形成的方案数就是在两个点的子树中各选\(k\)个点,
然后两两任意配对的方案数,也就是\(f[i][k]\times f[j][k]\)
所以我们要求的只有\(f[i][k]\),把它记做\(f_i\)。
我们把每一个点的\(f[i][j]\)看成一个多项式\(P_i(x)\)
考虑每个点的这个多项式是怎么来的,
显然是每个子树的\(size\)可选可不选(也就是进不进子树),那么就是$$\prod_{v\in Son_i}(1+size_vx)$$
这个多项式的每一项代表着一个\(dp\)值,这个多项式
那么总方案数\(f_i\)就是\([x^k]P_i(x)\times A\) ,其中\(A=1+x+x^2+...\)
也就是$$f_i=\sum_{i=0}kP_i[xi]$$
我们显然可以分治\(FFT\)求出每个点的\(P\)值,因为\(\sum son_i\)和\(n\)同阶。
所以复杂度是\(O(nlog^2n)\)。
但是,注意一个问题,这种情况是在根确定的情况下,并且枚举的两点的\(lca\)并非这两点本身。
如果\(LCA\)是两点\(u,v\)中的某一个点,那么不妨设是\(u\)
那么\(u\)的\(P_u\)显然不是我们提前求出来的\(P\),它需要减去\(v\)所在的子树的贡献,然后加上它父亲作为子树的贡献
假设\(v\)所在的子树的那么根是\(a\),\(a\in Son_u\)
然后把它的父亲节点看成一个子树算进去。
显然是$$P_u(x)\times \frac{(n-size[u])x+1}{size[a]x+1}$$
这个没必要卷积,\(O(n)\)做即可,因为\(size\)相同的子树可以合并,
所以在极端情况下,所有点的\(size\)不同的儿子最多只有\(\sqrt n\)个
所以总复杂度不会超过\(O(n\sqrt n)\)。
这样的话分别考虑上述两种情况,让每个点作为\(LCA\)就可以线性计算了。
总的时间复杂度\(O(nlog^2n+n\sqrt n)\)。
模数\(10^9+9\)十分蛋疼,需要\(MTT\)
这题太毒瘤了,我就当一个口胡选手得了。
T3.i
题意
给定三个函数\(f,g,h\)
定义
给定\(n\),求\(h(n)\)
题解
打表(或者\(OEIS\)之类的),发现\(f(n)\)的意义是\(n\)这个数在整个数列中出现的次数,并且\(f(n)\)单调不降。
那么\(g(n)\)是\(f(n)\)的前缀和,含义就是\(f(x)=n\)的最大\(x\),也即\(n\)在数列中最后一次出现的位置。
\(g(f(n))\)的含义是什么?\(f(n)\)在数列中最后一次出现的位置
\(f(f(n))\)的含义是\(f(n)\)在数列中出现的次数。
那么\(f(n)\)最后一次出现的位置减去\(f(n)\)在数列中出现的次数,
这个值显然就是\(f(n)-1\)最后一次在数列中出现的位置,也即\(g(f(n)-1)\)
那么\(g(g(n))\)怎么算呢?
我们差分算一下
所以,\(g(g(n))=g(g(n-1))+nf(n)\)
所以,$$g(g(n))=\sum_{i=1}^n if(i)$$
我们再看看\(h(n)\)的式子,现在就变成了
我们看看括号里面的东西,表示的是在数列中,\(f(n)-1\)这个数最后一次出现的位置
如果把所有的\(h\)一步步拆开,那么我们发现它就是一堆\(g(g(x))\)的和。
所以我们考虑所有的这样的和,发现每一次都是把\(f(n)\)的值减一然后进行计算,
最后当\(f(n)=1\)时停止。那么我们倒着来,
依次把所有的\(f(n)=x\)的数加入进\(g\)值中,然后累加起来,这样我们就可以得到最后的答案了。
因为\(f(n)\)不会太大,所以\(f\)值只需要算到\(10^6\)左右,这样子可以把\(f\)相同的数给合并起来。
总结
今天的题目非常神仙,\(T1\)乱搞题,\(T2,T3\)都有点神仙了。
今天如果乱搞比较到位,应该可以拿到\(100+50+10=160\)的成绩吧
然而最后只有\(40+50+10=100\),显然比较差了。
所以,还是一些奇奇怪怪的地方稍微注意一下,乱搞的时候也要注意一下一些潜在的问题,
可能导致乱搞\(re\),(比如\(rand\)数的时候发现值域是空集,就不需要\(rand\)了)
这段时间好好调整状态,让自己考试渐入佳境吧。
Day4
今天的题目来自于退役了还要毒瘤的\(wfj\_2048\)
流水账
只要是\(wfj\)的题目,我就知道今天要凉。
\(T1\),\(HNOI2018\)看错题版本。一脸会看着\(O(n^5)\),实际\(O(n^4)\)的东西。
发现可以拿到\(30\)分,非常开心。
发现一个很明显的贪心,如果当前点选择修,如果它的祖先的边中有没修的,那么一定会修祖先。
但是并不知道有什么用。
感觉可以给每次修边操作二分一个权值,然后让他恰好做\(n-1\)次,然而并不知道怎么写。
接着看\(T2\),爆搜,再见。
\(T3\),我连\(O(n^2)\)的暴力都懒得打。
期望得分\(30+15+0=45\)
实际得分\(30+15+0=45\)
一分都没有丢,很开心。
简单的题解
T1.y
题意
同\(HNOI2018\ D2T3\),把每个儿子修一条边更改为可以任意修\(n-1\)条边
题解
\(tags:\)凸优化,贪心,\(dp\)。我不会做。留坑。
T2.s
题意
给定一个\(n\times n\)的方格,保证\(n\)是奇数,令\(m=(n+1)/2\)
每次可以把\(m\times m\)的子矩阵全部取反,
求矩阵元素的和的最大值。
题解
结论题,留坑。
T3.f
题意
数据结构题,需要维护的操作见题面
题解
\(tags:\)动态\(dp\),\(Link-Cut-Tree\)。留坑。
总结
没有打挂,很开心,阿鲁巴了\(wfj\),很开心。
Day5
今天的题目来自于雅礼的两个人。
流水账
开考看\(T1\),感觉像个网络流。
一开始一直在想怎么强制让一条边要么流的容量为\(2\),要么不流。
但是显然这样不可行。一个多小时都没有什么思路。
后来忽然发现可以把偶点做二分图,中间用奇点连起来,这样就可以了。
然后就写完了。
忽然有人告诉我是洛谷原题。今天IOI赛制?
\(T2\)没感觉,一眼\(5\)分我会\(return\ 0\)
看\(T3\),一开始没有任何感觉。
后来忽然发现确定了左端点之后所有东西都是单调的,
也就是最多只有一个点满足条件,可以直接二分。
那么就只需要快速求一个子串的字典序排名。
一开始还是没有感觉,后来忽然就会做了。
求出\(SA\)再分类讨论,随便二分一下就好了,然后就写完了。
期望得分\(100+5+100=205\)
实际得分\(100+5+70=175\)
发生了什么?
应该是:
int RMQ(int l,int r)
{
int k=lg[r-l+1];
return min(hg[k][l],hg[k][r-(1<<k)+1]);
}
我写成了:
int RMQ(int l,int r)
{
int k=lg[r-l+1];
return hg[k][l]+hg[k][r-(1<<k)+1];
}
亮点自寻。这样都TM能过70分?数据得有多水?
题解
T1.marshland
题意
给定一个\(n\times n\)的矩阵,所有\(i+j\)为奇数的格子都有一个权值
现在有\(m\)个\(L\)型,占\(3\)个格子的东西。可以使得拐角的那个格子的权值变为\(0\)
可以不全部用掉,问最小的权值和。
题解
我们假设有权值的点是黑点,没有权值的点是白点。
那么每次一定是选择两个白点和一个黑点然后覆盖。
所以我们选择了一个黑点之后,就不能再选择与之匹配的两个白点。
如果我们按照黑点建边,连向白点,发现有一个问题:
可能会有黑点只流出去了一点流量,而并非满流。
我们没有办法可以限制一条边要么满流要么不流。
我们换一下思路。考虑到一定是选择一个白点,然后匹配一个白点。
这个时候相当于是将这两个白点之间的黑点的权值变成了\(0\)
所以将白点放在两边,形成一个类似于二分图的东西。
同时每个黑点只能够被有用一次,所以拆点,中间用它的权值作为边的费用。
发现这样子还是有问题,如果把所有的白点都拆成两个显然是错的。
我们发现两个白点一定不在同一列,一定在相邻的两列(行也是一样的)
所以按照每个白点在哪一列进行黑白染色分成两边,
强制从奇数列连向偶数列就行了。这样子就没有问题了。
T2.party
题意
有一棵树,只能从儿子走向父亲。每个点有一个颜色。
每次询问\(K\)个点,要使得所有点都在他们到\(LCA\)的路径上选择若干个点所具有的颜色。
要求每个人选择的集合没有交集,并且所有的集合大小相同。求并集的最大值。
题解
显然可以用\(bitset\)维护出每个人到\(LCA\)路径上出现的所有颜色。
那么,现在就是每个人只能带某几种颜色了,并且颜色不能存在交。
这就是一个二分图匹配。如果暴力做显然是二分后拆点+匈牙利计算答案。
事实上并不需要,考虑\(Hall\)定理:
如果存在完美匹配,那么任意选择\(K\)个左侧节点,他们连向右侧节点的并的大小不小于\(K\)。
我们算出选择任意个节点的颜色的并,这个可以状压递推解决。
根据\(Hall\),定理,如果\(x\)是答案的话,那么对于任意状压后的状态,都有:
当前状态的人数乘上\(x\)要大于当前状态的颜色的并的集合大小。
所以\(x\)就是所有状态的集合大小整除这个状态的\(1\)的个数的最小值。
有个优化,树链剖分求\(lca\)到当前点的集合的并,并不需要树链剖分\(log\)再加上线段树\(log\)
可以提前预处理出每个点跳到重链顶端的集合,然后先跳掉和\(lca\)在同一个重链上,再用线段树查询
这样跳重链和线段树的操作就分离开了,复杂度只有一个\(log\)
综上,本题时间复杂度\(O(nlogn\frac{m}{64})\)
T3.platform
题意
给定一个串,对于这个串所有本质不同的子串按照字典序从大到小排序
给定每个位置一个权值。
求出所有的\((l,r)\),满足\([l,r]\)构成的子串的排名等于\([l,r]\)的权值和。
题解
确定左端点之后,发现权值和一定是单调递增的,而子串的排名一定是单调递减的。
所以这两个函数最多只会存在一个交点,所以可以二分这个位置。
那么现在的问题很明显就变成了如何快速计算一个子串的排名。
思考如何用\(SA\)一个串中本质不同的子串的个数,显然是\(\sum\)后缀长度-\(height\)
这个的意思是按照字典序排序之后,每个后缀能够贡献的本质不同的子串的个数就是
当前这个后缀的长度减去这个后缀和排名在他前面一位的后缀的\(lcp\)
所以考虑当前子串\([l,r]\)的排名。
如何\(l\)这个后缀的和排名前一位的后缀的\(lcp\)在\(r\)之前,
显然答案就是\(\sum_{i=1}^{rk_i-1}len_{SA[i]}-height[i]\),再加上\(r-l+1-height[rk[l]]\)
这个东西显然可以求出后缀数组之后用前缀和预处理好。
如果与排名前一位的后缀的\(lcp\)包含了\(r\)位置,证明这个串在前面的后缀中曾经出现过。
现在就需要找到它第一次出现的位置。
等价于找到排名最靠前的,与后缀\(l\)的\(lcp\)要大于等于\(r-l+1\)的那个后缀。
因为\(lcp\)单调不升,二分之后用\(RMQ\)
时间复杂度(可能是)\(O(nlog^2n)\)
总结
今天虽然考的还行,但是又犯了智障错误。真的很不应该啊。
虽然\(SA\)的确很久没打过了,但是这不是\(RMQ\)的\(min\)写成加的理由,一定要注意这些问题。
不过今天\(T1\)的数组还是注意了空间问题,\(T1\)没有挂。
考场背\(SA\)竟然没有写错,好感动。
Day6
今天的题目来自喻队和另外一位麓山的学长。
考试心理历程
上来就看\(T1\),表示毫无感觉。
然后看\(T2\),也没感觉。
然后看\(T3\),依旧没有感觉。
这是\(wfj\)的既视感?
再回头看\(T2\),似乎可以容斥。
那么就是任选的贡献,一条边的贡献,两条边的贡献,和三元环的贡献。
调了很久把\(T2\)写完了。
\(T1\),我会全是数字和\(next\_permutation\)
\(T3\),我会暴力\(Hash\)
期望得分\(20+100+20=140\)
实际得分\(30+70+0=100\)
蛤?\(T3\)用了\(C++11\),然后我开了一个叫做\(hash\)的数组,成功的\(CE\)
\(T2\)中间有一个地方我直接写了除法,然而可能会直接取模了,导致有些点\(WA\)了。
我也很无奈啊。
简单的题解
T1.gift
题意
定义两个排列的相似度为不停交换两个元素直到两个排列相同的最小操作次数。
给定两个排列,排列中有些数为\(0\),表示未知的数。
求所有相似度\(\in [0,n)\)的方案数。
题解
考虑一下如果所有数我们都知道了,应该怎么计算相似度。
有一个\(O(n^2)\)的做法,从头到尾扫\(A\)数组,如何对应位置相同,则什么也不做。
否则找到\(A\)数组中,当前位置对应的那个数字,交换一下,答案贡献增加一。
我们把这个模型提取出来,也就是从我们当前的\(A[i]\)连边连到对应的\(B[i]\)
这样就形成了一个环,显然是环里面的所有点顺次交换。
所以一个大小为\(x\)的环产生的交换次数为\(x-1\),所以差异度就是\(n\)减去环的个数。
现在的问题在于有些边我们是未知的,所以现在连出来的东西要么是个已知的环,要么是条链。
环对于我们计算没有太大的影响,可以暂时不用考虑,对于链而言,中间的部分是没有任何意义的,
需要考虑的只有头和尾两个点。这样子也只有三种链\(0-x,x-0,0-0\),左右两个东西分别表示头和尾。
其中,\(0-0\)的链十分自由,暂时不考虑。
剩下的\(0-x\)的链和\(x-0\)的链我们考虑把它们接在一起。
发现只能\(0-x-0-x\)或者\(x-0-x-0\)这样接,
不存在\(0-x-x-0\)这样接,如果这样的话,这两条链显然是同一条链,会被合在一起计算。
也不存在\(x-0-0-x\)的链,因为中间由\(0-0\)组成,需要额外考虑\(0-0\)链的影响。
我们现在要考虑的只有环的情况,那么设\(f[i]\)表示用若干相同的\(x-0\)或\(0-x\)的链,产生至少\(i\)个环的方案数。
因为不好直接计算,我们设\(f[i]\)表示至少产生\(i\)个环的方案数。
我们可以得到如下的式子:$$f[x]=\sum_{i=x}nC_nS_ixA_{m+n-x}$$
其中\(n\)是当前类型的链的数量,\(S\)是第一列斯特林数,\(C\)、\(A\)分别表示排列和组合,\(m\)表示\(0-0\)边的数量。
什么意思呢?
形成\(x\)环最少要\(x\)条链,我们先从\(n\)条链中选择\(i\)条链来拼成\(x\)个环,他们拼接的方案数显然是第一类斯特林数。
剩下的当前种类的链的个数是\(n-i\)个,因为对于\(x-0\)或\(0-x\)我们已经知道了一侧,
如果要连起来,我们显然需要选择另外一侧,所以我们给他们来选择前驱(后继)
这个前驱(后继)可以是一条别的链,可以是\(0-0\)链,也可以自己连向自己形成环。
这样子就可以保证至少有\(x\)个环。接下来容斥一下,就可以算出恰好有\(x\)个环的方案数。
对于\(x-0\),我们设算出来的结果为\(f[i]\),对于\(0-x\)链,我们算出来的结果是\(g[i]\)
现在唯一剩余的情况,就是用\(0-0\)链合并\(0-x\)链和\(x-0\)链
先把\(f\)和\(g\)做卷积,这样表示用两种链形成若干环的情况的答案,并且剩下的链一定都是\(0-0\)链。
为什么剩下的都是\(0-0\)链?如果在前面选择前驱(后继)的时候,要么就会若干个连成一个一个环,
要么就是最终连到了一个\(0-0\),此时开头和结尾都是\(0-0\)
那么,现在就是一堆\(0-0\)链连成环的方案数了。这个答案现在还是第一类斯特林数。
但是因为\(0-0\)边没有确定的起点或者重点,因此还需要额外乘上一个阶乘。
T2.girls
题意
求所有满足条件的三元组\((i,j,k)\)的贡献\(A\times i+B\times j+C\times k\),其中\(i\lt j\lt k\)
其中有\(m\)个限制\((u,v)\),表示\(u,v\)不能同时选。
题解
我们把选择出来的东西看做点,限制叫做边。
考虑容斥,首先我们计算任选三个点的方案数,然后减去选择了一条边然后另外一个点任选的贡献。
再把选择了两条边的贡献加回来,再减去三元环的贡献。
前面都只需要枚举边或者枚举点就好了,都可以做到线性的复杂度。
三元环的求法比较有趣,
我们把所有的边强制定向,由度数大的连向度数小的,度数相等按照编号连。
这样子我们暴力枚举一条边,然后就确定了两个点。
把其中一个点的所有出边到达的点打个标记,再检查一下另外一个点是否有标记就好了。
这样的复杂度?
这样连完边后,每个点的出度都不会超过\(\sqrt m\)。
证明?
我们的点分成了两类,一类是度数小于\(\sqrt m\)的,另外一类是大于\(\sqrt m\)的,其中\(m\)是边数。
对于一个度数小于\(\sqrt m\)的点,它的度数本来就不超过\(\sqrt m\),那么定向后也不会大于\(\sqrt m\)
对于一个度数大于\(\sqrt m\)的点,它的所有出边都连向度数大于\(\sqrt m\)的点,
因为边的总数是固定的,所以这样的点的个数不会大于\(\sqrt m\),
所以总的复杂度不超过\(O(m\sqrt m)\)
T3
题意
给定\(n\)个字符串,要求在线支持以下操作
在一个字符串后面添加一个字符。
询问第\(y\)次操作之后的一个串\(x\),在当前的串\(z\)中出现的次数。
询问当前所有串的本质不同的子串个数。
询问一个串\(T\)在所有给定的串中出现的次数的最大值。
题解
留坑
总结
没有多少天了。希望能够找到自己状态吧。最近的题目都有点不是很可做。(对我而言)
导致考场上并没有那么认真的思考,希望接下来的题目能够回归正常吧。
Day7
我很想知道今天的题目来自谁。
流水账
没什么好说的,毒瘤题\(\times \infty\)
不全的题解
T1.inkmaster
题意
给定一个仙人掌,每个点可以染一种颜色,每条边对应的两个点的颜色不能相同。
多次询问,每次告诉你有多少种颜色,问染色的方案数。
题解
考虑一棵树的贡献,从上往下考虑,显然对于每个点有影响的点有且仅有父亲
所以每个点的颜色只是不能与父亲相同,所以答案是\(C\times(C-1)^{n-1}\)
现在回归仙人掌。显然对于答案有影响的从只有父亲,
变成了对于返祖边的终点,还有求与这个环的最底端颜色不同。
那么,如果这个环的颜色确定了,对于其它的环也没有任何影响。
所以我们把所有的环全部找出来计算。
因为大小相同的环本质上是一样的,所以可以开桶记录所有的环的大小。
每次计算一下环的贡献,最后全部乘起来就行了。
考虑一个环的贡献,我们断环成链,贡献是\(C\times(C-1)^{n-1}\),
减去首尾颜色相同的贡献,也就是\(C\times (C-1)^{n-2}\)。
这个时候,我们可以把头尾缩起来,看成一个点,但是这个时候似乎又多计算了一些东西。
所以我们这里相当于是一个容斥。并且贡献是一个等差数列,可以快速幂\(log\)算。
因为长度不同的环的个数最多不会超过\(\sqrt n\)个,
所以每次询问的复杂度就是\(O(\sqrt n\ log n)\)
总复杂度\(O(q\sqrt n\ logn)\)
T2.branching
题意
给定一棵树,有两种走法,一种是随机选择一个点并移动过去,另外一种是沿着一条边走。
求从点\(u\)到达\(v\)的最短步数的期望。
题解
每个点到达目标点的走法一定是先随机若干次,到了一个比较优秀的点的时候就直接走过去。
那么,这个东西显然有一个阀值,如果一个点距离目标点的距离大于阀值则继续随机换点。
现在考虑如何求解这个阀值。考虑二分,我们假设二分值为\(x\)
那么有:$$x=1+\frac{\sum min(dis,x)}{n}$$
那么现在的问题就是求出到达所有点的\(dis\)了。
这个东西可以用动态点分治进行计算,时间复杂度是\(O(nlog^3n)\),听说可以做到两个\(log\)。
还有一种比较玄学的做法,考虑一下最大的答案,这个答案一定在一条链上,并且目标点是一个端点。
那么打表可以得到,在本题的数据范围内,最大的答案不会超过\(500\),
那么可以预处理出距离每个点距离不超过\(500\)的所有点的距离和,这样就可以直接算了。
T3.euclid
题意
给定两个矩阵,求$$\sum_{x=1}LAxB^{\frac{Px+r}{Q}}$$
题解
留坑。
总结
题目越来越毒瘤了。总结也越来越短了。因为我也不知道可以写什么了。
Day8
今天的题目来自于一中。
考试的五个小时
上来先把题看了一遍,\(T1\)一眼会\(75\)分,\(T2\)题面好长,先跳了。
\(T3\)???这不是傻逼题吗?为什么数据范围这么小?
这不是个傻逼题吗?我不会看错题了吧。
真的没看错?那就是道傻逼题。。。。。
写完过了大样例,非常自信,顺带自己\(yy\)一下,这题做\(10^6\)都随便做啊。。
\(T1\)想了想正解,发现没有思路,怎么算复杂度都是假的。
所以暴力\(AC\)自动机+线段树维护矩阵(一脸我出的那题的感觉),顺手码完\(75\)分。
回头看\(T2\),顺手退火了,各种调参什么的过了样例。
然后就开了几局空当接龙。
期望得分\(75+?+100=?\)
实际得分\(65+8+100=173\)
听说\(T2\)直接\(return\)就过了,\(SPJ\)好迷啊。
\(T1\)正解是把\(AC\)自动机上被标记的点全部删去再向我那么做?
我怀疑我会分分钟把\(std\)卡掉,这复杂度显然是假的啊。。
题解
T1.kill
题意
给定一个二进制串,一些位置已经给出,其它位置随便填。
给定若干个不合法的模板串,每次询问一个区间\([L,R]\)能够组成的所有串中,合法串的总数。
同时支持单点修改位置是给定还是任意。
题解
先构建\(AC\)自动机,然后显然是每次在上面\(dp\)
这个过程我们肯定不能每次都模拟一遍,所以把转移压进矩阵。
有一些冗杂的值不需要存进矩阵,就是那些不合法的\(AC\)自动机上的状态。
然后用线段树快速维护一下矩阵乘法就好了,时间复杂度\(O(nlogn|S|^3)\)
T2.politics
因为有点假,所以就自己看吧。
T3.eat
题意
给定\(n\)个集合,所有集合元素个数的并不超过\(m\),每个元素选或者不选都可以得到一个权值,
求任选\(k\)个集合的交的权值的期望。
题解
题目逗逼了。
直接分开考虑每个元素,算一下它的出现次数就好了。
时间复杂度\(O(\sum|S|+m)\),复杂度瓶颈在于读入。
然而这题可以改一下,更改为给定所有由这些元素构成的集合的权值,求期望。
这样子只是把求每个位出现的次数变成了计算每个交出现的次数。
那么,我们容斥计算就好了。
先计算出选择当前集合\(S\)的子集的方案数,再用它的子集去减掉就好了。
这个过程就是\(FWT\)的过程。
总结
今天的题目很多锅,所以我的总结都越来越短了。
Day9
今天的题目来自于衡八。
Test
看了一遍题目,感觉好难。
忽然觉得\(T2\)我会做\(m=1\)和\(2\)的特殊情况。
于是就写了一下。
忽然发现自己会这道题目了,只需要先枚举一下左右的颜色个数,再用组合数算方案就好了。
然后\(T1\)和\(T3\)写完暴力就滚粗了。
题解
T1.circle
题意
给定一个竞赛图,钦定其中\(K\)个点,回答在这\(K\)个点以外,最少去掉多少个点使得图不存在环
题解
留坑。
T2.color
题意
给定一个\(n\times m\)的矩阵以及\(K\)中颜色,可以任意染色。
要求改矩阵从任意列分开,左右两块包含的颜色数相同,求染色方案数。
题解
显然左右两列的颜色数量相同,中间染的颜色一定是两侧颜色的交。
那么枚举用了几种颜色\(a\),以及两侧颜色的交\(b\)。
那么,此时贡献的方案数就是从\(K\)种颜色中选出\(a+a-b\)个,
此时选择颜色的方案数是\(C_k^b\times C_{k-b}^{a-b}\times C_{k-a}^{a-b}\)
然后考虑左右染色的方案数,显然是把\(n\)个格子染成\(a\)中颜色,
这个方案数是第二类斯特林数乘上阶乘,中间的格子用快速幂算就可以了。
T3.simulate
题意
给定一个由\(012\)组成的数组。
每次都将大于等于而的所有数减去二,然后其左右两侧的数各加上一。
当没有大于等于二的数时停止,求终止的数列。
题解
留坑。
总结
\(Last\ Day\),结束了。
这段时间犯了各种各样的奇奇怪股的错误,这个是真的很不应该。
从另外一个方面来说,这段时间也接触到了很多有趣的东西。
总而言之,收获还是有的吧。
当然,现在我非常想睡上一天了。