• 2018HN省队集训


    HNOI2018省队集训

    Day 1

    流水账

    T1 tree
    换根+求(lca)+求子树和,一脸bzoj3083遥远的国度的既视感。子树和讨论一下就好了,(lca)?也是大力讨论一波。
    先写了个线段树标记永久化,一发过了小样例,然后大样例。。。没几组询问就(WA)了。写了个暴力,每次输出求出来的(lca)(我怎么这么机智啊),发现(WA)了,然后就对着自己的大力讨论大力魔改。大概是(10:00)的时候大样例终于过了,没写拍(因为不会写(win)下的拍qaq)。
    T2 function
    看出来了结论,一直在(yy)怎么用斜率搞一搞。最终还是没能(yy)出来,交了个(42)的暴力。
    T3 or
    一开始还以为自己只会写(O(n2^k))的暴力(dp),然后转念一想其实二进制位都是等价的,就写了个(O(nk^2)dp)过了样例。最近有些(ntt)上瘾所以当然是顺手敲了发(ntt)
    预估得分(100+42+59=201),实际得分(83+42+59=184)
    T1被卡常qaq,我活该大常数。

    总结

    得分比较稳定,该拿得分基本上都拿到了(卡常这件事出题人自己也没想到)。T2在考场上缺乏去硬刚的信念与勇气导致没有做出来。T3的正解比较神仙。

    简要题解

    tree

    在换根的前提下子树有三种情况:若询问点不是根的祖先则子树就是原来的子树,若询问点就是根则子树就是整棵树,若询问点是根的祖先则子树是整棵树除去根所在的询问点的那个儿子。这部分就是bzoj遥远的国度
    (lca)的情况相对复杂一些:若两个点都在根的子树中则(lca)就是在原树中的(lca),若一个在一个不在则(lca)就是根,若两个都不在,需要判断两点路径和根到(1)号点路径有没有交,也就是判断两点在原树中的(lca)是不是根的祖先,若不是则(lca)还是原树中的(lca),否则(lca)是路径交中深度最大的那个点。

    function

    首先一组询问((x,y))的答案是(min_{iin[1,y]}S_y-S_i+A_i(x-y+i)),其中(S_i)(A_i)的前缀和。
    (x-y)为自变量,相当于在所有形如(y=A_ix+A_ii-S_i)的直线中找一个最小值,维护下凸壳就行了。
    由于存在一些特殊性质所以可以用单调栈维护凸壳。

    or

    首先观察一下(dp)式:

    [dp[i][j]=sum_{k=1}^{j}dp[i-1][j-k] imesinom{j}{k} imes2^{j-k} ]

    也就是

    [frac{dp[i][j]}{j!}=sum_{k=1}^{j}frac{dp[i-1][j-k] imes2^{j-k}}{(j-k)!} imesfrac{1}{k!} ]

    构造指数型生成函数

    [F_i(x)=F_{i-1}(2x) imes (e^x-1) ]

    (e^x=sum_{i=0}^{infty}frac{1}{i!}x^i)(F_{i-1}(2x))是因为把(2^{j-k})和生成函数里的(x^{j-k})合并了)

    [F_n(x)=prod_{i=0}^{n-1}e^{2^ix}-1 ]

    (n)是偶数的时候满足(F_n(x)=F_{frac n2}(x) imes F_{frac n2}(2^{frac n2}x))
    所以倍增求一下就好了,分(n)是奇数还是偶数讨论一下(偶数直接除二,奇数减一变成偶数)

    落实情况

    题目 tree function or
    完成情况 corrected corrected corrected

    Day 2

    流水账

    T1看了半天发现是不会做的。先写了(30pts)暴力,然后发现“只有一个质因子”就可以完全按照大小来做,就写了个(BIT)(结果(laofu)说值的个数很少只要开桶就行了)
    T2先写了个暴力打个表,想着(40pts)的状压结果推出来了一个(O(n))的式子,直接就(80pts)了。
    T3(10pts)暴力
    T2打表,块大小(50w)打了(60k)(三个表),本机跑极限数据开(O2)(5s)
    预估得分(40+80+10=130),实际得分(40+0+10=50)
    由于日常考试分不清到底测文件夹内还是文件夹外所以习惯性地把三份代码都粘到文件夹外,我也不知道为什么就按成了(Ctrl-x)。于是愉快地“未找到源程序”qaq。
    以后这种事情还是不要干了吧。

    总结

    我觉得这个分应该是我的极限实力了吧qaq。

    简要题解

    walk

    留坑

    game

    首先(O(n))的答案式是(n!-2sum_{i=0}^{n-1}i!+sum_{i=0}^{n-2}i!(n-i-1)+1)
    大力开一下$$原式=n!-2sum_{i=0}^{n-1}i!+(n-1)sum_{i=0}^{n-2}i!-sum_{i=0}^{n-2}i! imes i+1=n!-2sum_{i=0}^{n-1}i!+(n-1)sum_{i=0}^{n-2}i!-sum_{i=0}^{n-2}[(i+1)!-i!]+1=n!-3sum_{i=0}^{n-1}i!+nsum_{i=0}^{n-2}i!+2=(n-3)sum_{i=0}^{n-1}i!+2$$
    所以就只要求一个阶乘前缀和,打表阶乘以及前缀和即可。

    string

    询问离线,从小到大枚举(r),维护每个左端点的答案。
    有一个这样的性质:一个串的所有回文后缀一定可以被分为不超过(log n)个等差数列。
    先考虑最长回文后缀,那么所有长度超过它的一半的回文后缀一定会构成等差数列(这个画画图就好了),要想不满足等差必须让长度减小一半,所以最多只有(log n)个等差数列。
    每个等差数列会让一段连续的(l)的答案增大(1)。具体来讲,这一段的左端点是等差数列中最大的回文后缀上一次出现的位置+1(如果之前没出现过就是(1)),右端点是等差数列中最小的回文后缀的出现位置。
    用线段树维护每个回文后缀最后出现的位置(为保证复杂度修改的时候只能修改最长回文后缀,所以查询的时候要查该回文后缀在回文树上的整棵子树),然后用树状数组维护每个左端点的答案。

    落实情况

    题目 walk game string
    完成情况 N/A corrected corrected

    Day 3

    流水账

    T1想了一个(O(nlog^2n))的假算法,过了大样例,感觉很对的样子。
    T2看上去像是个(dp),不管了先去做T3。
    T3打表,观察规律无果,(10pts)滚粗。
    发现T1的算法是假的,但是并没有想到正解。
    T2(yy)了半天写了一个(O(n^3))的做法,下考前写了链,感觉(O(n^2))的做法也不是很难,只是没有想清楚具体怎么实现所以就没有写。
    预估得分(??+50+10=??),实际得分(95+50+10=155)
    没想到T1乱搞有(95)分,据说还有乱搞(AC)的。

    总结

    在T1上面纠结了太久,导致T2没有把分数打满。如果是在满状态下开T2的话应该可以拿到(80)分的样子吧。

    简要题解

    c

    破环成链,对于(l<r)的线段,新加入线段([l+m,r+m]),否则加入线段([l,r+m])。这样就需要选出一个长为(m)的区间包含尽可能多的不相交线段。
    考虑强制每一条线段作为第一条线段,根据贪心,每选过一条线段之后下一条选的线段是确定的。不妨记为(nxt_i),那么我们只关心每一条线段跳多少次(nxt)后达到(m)长度。把(nxt)数组倍增实现即可。

    a

    暴力枚举这(k)个人路径的交,这肯定是树上的一条简单路径。那么这条路径对答案的贡献就是(f_x imes f_y),其中(x,y)是枚举的两个点,(f_x)表示在(x)的子树中选出(k)个点使得两两(lca)(x)的方案数。
    如果(x,y)其中一点是路径的(lca),不妨设是(x),那么对答案的贡献应该是(g_{x,y} imes f_y),其中(g_{x,y})表示点(x)(y)为根方向时的(f)值。
    考虑满足“两两(lca)(x)”这一条件,显然需要有若干个点在(x)上,然后在(x)的每个子树中选至多一个点。
    设一个多项式(P_x(x))表示在(x)中选出(i)个子树的方案数的生成函数,鉴于每棵子树只能选一个,所以(P(x)=sum_{son}(1+size_{son}x) imes(1+x+x^2+x^3+...)),对于每个点分治(FFT)即可,这样的总复杂度是(O(nlog^2n))的。
    然后求(f)的话就是(sum_{i=0}^{min(k,deg_x)}A_k^i imes [x^i]P_x(x)),算这个的复杂度是(O(n))的。

    这样可以求出所有的(f),至于求(g_{x,y}),其实就是求其生成函数(Q_{x,y}(x)=P_x(x) imesfrac{1+(n-size_y)x}{1+size_yx}),这个东西是一个多项式除以二项式的形式,是可以做到(O(deg))的。具体使用姿势可以参考(CTSC2018)假面一题。

    这样对于每个儿子都直接(O(deg))求一遍的话复杂度可能会退化成(O(n^2))。发现除掉的内容只和子树(size)有关,而一个点不同大小的儿子最多只有(O(sqrt n))个,所以只要记一下,对(size)相同的儿子不重复处理即可。复杂度(O(nlog^2n+nsqrt n))

    i

    打表发现(f(i))表示(i)在序列中出现的次数。
    考虑一些东西的实际含义:(g(i))表示前(i)个数出现的总次数,那么也就是第(i)个数最后出现的位置。
    又因为(g(i))(f(i))的前缀和,所以(g(f(i))-f(f(i))=g(f(i)-1)),表示最后一个值为(f(i)-1)的位置(下标)。
    也就是说(h(i))就表示从(i)往前每一段相同数字的最后一位的(g(g(i)))之和。
    考虑(g(g(i)))怎么求。

    [g(g(i))-g(g(i-1))=sum_{j=g(i-1)+1}^{g(i)}f(i)\=sum_{j=g(i-1)+1}^{g(i)}i=i imes f(i) ]

    所以(g(g(i))=sum_{j=1}^{i}j imes f(j))
    打表可以发现当(n)达到(10^9)(f(n))不会超过(10^6),所以可以按照(f(i))分段处理,复杂度大概是(O(T imes10^6))

    落实情况

    题目 c a i
    完成情况 corrected N/A corrected

    Day 4

    流水账

    (wfj)的题,预感大事不妙。
    T1这显然就是(wfj)在考场上看错题的那个版本吧。强行给(HNOId2t3)加一维状态复杂度大概是(O(n^2d^2))?反正能过前两个(subtask)
    T2只会(O(2^{x^2}n^2))的暴力。
    T3我发现我不会(O(n))做后面两问,所以就爆零了。
    想写个T2的退火,结果没有获得比暴力分更高的分数。
    大概是(12:00)的时候一群一中(dalaoAK)离场了,好强啊。
    预估得分(30+15+0=45),实际得分(30+15+0=45)
    不得不说稳得一匹。

    总结

    希望接下来的几天里没有今天这样的毒瘤场。
    p.s. (wfj)被阿掉了(不过他本人似乎还不满足?)

    简要题解

    y

    凸优化

    s

    套结论

    f

    不会

    落实情况

    题目 y s f
    完成情况 N/A N/A N/A

    Day 5

    流水账

    T1一眼网络流的既视感,一开始想着建立二分图,然后。。。一个黑点匹配两个白点?还要最大权匹配?不太可做吧。感觉自己不太会写(30pts)的状压(dp),只要硬着头皮刚正解。
    大概是(9:00)左右的样子灵感突显:拆成一个三分图。然后二十分钟敲完费用流,一测大样例就过了,爽。
    T2看了一眼,就是用树剖维护(bitset)然后搞一搞,但是统计答案我不会啊,只好去看T3。
    T3这这这不是我哪天在洛谷上见过的原题吗?有一个很显然的结论:枚举左端点,右端点从左往右扫排名一定单调减,权值一定单调不降,所以就可以二分交点,问题转化为求一个子串在原串中的排名的问题。又是因为不太会写(30pts)所以选择刚正解,然后胡乱(yy)了一个(O(nlog^2n))的做法,希望不会被卡常。
    后来发现T1也是原题。跑到洛谷上交了两道题,于是莫名变成了(IOI)赛制。(虽然基本上都是一遍过的)
    T2发现了一种网络流统计答案的方法,但是写完T3已经(12:30)了,又觉得网络流应该跑不过几个点,就没写了(结果萝卜跟我讲网络流有(45pts)?)
    预估得分(100+5+100=205),实际得分(100+5+100=205)

    总结

    T2没有尝试更高的分数比较可惜。

    简要题解

    marshland

    我们称(X+Y)为奇数也就是有危险度的点为黑点,(X+Y)为偶数也就是没有危险度的点为白点。
    而白点内部又分为两类:行号(列号也行)为奇数和偶数的点,将其分别称为(1)类点和(2)类点。
    可以发现每一块石头都恰好覆盖了一个黑点、一个(1)类点和一个(2)类点。
    所以建立一个类似三分图的模型:(用((w,cost))表示容量为(w)费用为(cost)的边)
    (S)向每个(1)类点连((1,0)),把每个黑点拆成入点和出点,每个(1)类点向相邻的每个黑点的入点连((1,0)),每个黑点的入点向出点连((1,V_{i,j})),出点向相邻的(2)类点连((1,0))
    限制总流量不超过(m),即求的是最大费用可行流而非最大费用最大流。仔细想一想就会发现石头数量越多并不能保证解不更劣。

    party

    首先这几个人聚会的点一定是(lca)
    (bitset)维护每个点到树链剖分中这个点的(top)的路径并,再开一棵线段树维护区间并集。
    这样查询路径的时候就可以做到一个(log)
    考虑求出每个点到(lca)路径的(bitset),再求(dp(S))表示(S)集合中的点到(lca)路径的并。
    根据霍尔定理答案就是(min(frac{dp(S)}{|S|}))
    复杂度是(O((n+qclog n+q2^c)frac {m}{omega}))

    platform

    有一个很显然的结论:枚举左端点,右端点从左往右扫排名一定单调减,权值一定单调不降,所以就可以二分交点。
    问题转化为求一个子串在原串中的排名的问题,也就是求原串中有多少个本质不同子串的字典序比给定子串的要大。
    我们假设要算的是子串(S_{l..r})
    在后缀排序中排在(l)后面的所有后缀中本质不同的子串的字典序一定都比(S_{l..r})的要大。
    而排在前面的呢?一定没有吗?
    我们发现保证没有的情况当且仅当(S_{l..r})这个子串是在后缀(l)中第一次出现。
    如果是第一次出现那么可以直接计算答案(ans_{S_{l..r}}=sun_n-sum_{Rank_l}+n-r+1)
    否则我们就找到这个子串第一次出现的位置然后再计算即可。
    如何求第一次出现的位置?在(SA)上二分(lcp)即可。
    复杂度两个(log),然而比(std)一个(log)的线段树跑得还快qaq。

    落实情况

    题目 marshland party platform
    完成情况 corrected corrected corrected

    Day 6

    流水账

    浏览一遍题目以后发现只有T2比较可做,就想了想容斥那方面的,也就是计算所有包含(0,1,2,3)对矛盾的三元组。
    (0)想了蛮久怎么(O(1))算,然后。。。我选择写(O(n))的。
    (1)直接枚举边,感觉比(0)的还要好写一点。
    (2)的话枚举点,我开了个(vector)瞎搞,还带个排序的(log)。反正这也不是复杂度瓶颈。
    (3)就是前天晚上叶佬讲过的东西,这个结论的证明以及实现应该都不难。
    没造极限数据测,所以存在翻车的可能性。
    然后T1写了(A_i,B_i>0)的点,交了一个(O(n!^2))的鬼玩意。T3写了个(Hash)
    预估得分(20+100+20=140),实际得分(30+100+20=150)
    某人又被C++11卡CE了

    总结

    会写的都写了。T2没造极限数据测比较容易出锅,这次没翻不保证以后也不会翻。

    简要题解

    gift

    对于排列(a,b),连边((a_i,b_i)),这样会形成若干个环。每个环需要交换环长(-1)次,所以答案就是(n-)环的数量。
    现在我们的排列是不完整的,也就是说构出来的图也是不完整的。因为答案只和环的个数有关,所以我们可以把一些已经确定了的部分合并起来,这样图中就只剩下了四种东西:完整的环、起点确定终点不确定的链、起点不确定终点确定的链以及起点终点都不确定的链。
    我们求出每一种东西的个数,这个可以直接(O(n)dfs)
    发现完整的环在计算过程中是没有贡献的,只是把答案全部向右移了一位,所以可以不用考虑。
    我们需要用剩下的三种东西拼出若干个环的方案数,而实际上只要计算出用一种东西拼出若干个环的方案数然后卷积起来就可以了。
    对于起点终点都不确定的链,这个的方案数是(S[s1][i]),其中(S[i][j])表示第一类斯特林数,(s1)是这种链的数量。这个东西可以(O(n^2))求出。
    对于起点终点有一个确定的链,方案数不好直接求,但是可以求拼出至少(i)个环的方案数。
    (f[i]=sum_{j=i}^{n}C[n][j] imes S[j][i] imes A[m+n-j][n-j])
    其中(n)是这种链的数量,(m)是起点终点都不确定的链的数量,(S)是第一类斯特林数,(C,A)分别是组合数与排列数。
    然后做一个简单容斥即可。复杂度(O(n^2))
    注意最后还要乘上一个阶乘。

    girls

    总答案=任意三点的贡献-包含至少一对矛盾的三点的贡献+包含至少两对矛盾的三点的贡献-包含至少三对矛盾的三点的贡献。
    第一部分可以考虑枚举其中一个(O(n))计算。
    第二部分枚举边,计算剩下的(n-2)个点(O(m))
    第三部分枚举点,对一个点的相邻点排序,然后分当前点是最小、次小还是最大三种情况讨论,(O(nlog n))
    第四部分就是三元环计数,可以将无向图重定向,每条边都指向度数较大的那个点,若度数相同则指向标号较大的点。可以发现这样构出了一个(DAG),而且保证每个点的出度不超过(sqrt m)
    因为对于一个原图中度数小于(sqrt m)的点显然成立,对于一个原图中度数大于等于(sqrt m)的点,要连向他的点的度数至少大于等于(sqrt m),然后这样的点至多只有(sqrt m)个,于是证明这个结论成立。
    (DAG)中的一个三元环一定是有两条边共终点,我们考虑枚举剩下的那一条边,这样这条边起点终点的邻接点集合的交就是找出来的那些三元环。这样一来其实三元环的数量也不超过(msqrt m),复杂度(O(msqrt m))

    string

    落实情况

    题目 gift girls string
    完成情况 corrected corrected N/A

    Day 7

    流水账

    新一代的毒瘤题啊。
    T1只会写爆搜,然后写了树的(10pts)。(这好歹也是正解的第一步啊)
    T2想偏了,卡在高斯消元这个问题上,于是毫无进展,成功爆零。
    T3想写个(10pts)
    预估得分(20+0+10=30),实际得分(20+0+0=20)
    T3直接乘会爆(long long),所以需要加一些奇妙的东西或者直接int128

    总结

    其实今天的题目并没有想象中的那么毒瘤吧(毕竟自己还是可以改出来的)。
    可能是受到了周围环境的影响导致没有做到最好的投入吧。

    简要题解

    inkmaster

    对于树的情况,答案为(C imes(C-1)^{n-1})
    在仙人掌上,显然每一个环是独立的,我们在计算这个环的时候不算环根,这样把每个环的方案乘起来再乘个(C)就是最后的答案了。
    考虑每一个环,某个环如果直接按照树的方法去计算,会多算上首尾相同的方案,所以可以考虑容斥,减去强制首尾相同的方案(这时候倒数第二个点的颜色可能会与首尾相同),加上三个点相同的方案,减去四个...列出式子来就是:(假设环的大小不算环根是(sz)

    [(C-1)^{sz}-(C-1)^{sz-1}+(C-1)^{sz-2}+...pm (C-1) ]

    (pm)取决于(sz)的奇偶性)
    这是一个首项是(C-1)公比是(1-C)的等比数列,求一下和:

    [pm(C-1)frac{1-(1-C)^{sz}}{1-(1-C)}=pm(C-1)frac{1-(1-C)^{sz}}{C} ]

    这样就可以再(O(log n))的时间内计算每一个环的贡献了。
    现在的问题在于:环的数量可以是(O(n))个,一个个计算,复杂度是(O(qnlog n))
    发现式子只和环的大小有关,而一棵(n)个节点的树上不同大小的环的个数是(O(sqrt n))级别的。把大小相同的环的贡献放在一起算,复杂度就是(O(qsqrt nlog n))

    branching

    发现在每一个位置选择(2)操作的结果都是一样的,所以有一个比较显然的结论:存在一个(x)值使得对于所有距离终点不超过(x)的点都选择直接一步步走过去,而其余的点就选择进行(2)操作。
    设进行(2)操作走到终点的期望步数为(x),则有方程:

    [x=1+frac{sum_imin(dis(i,T),x)}{n} ]

    因为有一个(min)所以没有办法直接解这个方程,发现右边这个函数的斜率是递减的,可以考虑二分(x)。二分到整数即可,因为只要二分到整数以后,那个(min)里面哪些点取(dis(i,T))哪些点取(x)就已经确定了,就可以解方程算出(x)了。
    现在仅剩的一个问题在于怎么计算右式。我们发现就是计算距离(T)不超过(x)的点有多少个以及他们到点(T)的距离和。这个就直接动点分一下就好了嘛。
    自己写了一个(O(nlog^3n))的做法,题解做法是(O(nlog^2n))的,回去再看看qaq。

    euclid

    落实情况

    题目 inkmaster branching euclid
    完成情况 corrected corrected N/A

    Day 8

    流水账

    T1这这这线段树维护矩阵然后不就做完了吗。但是这个复杂度貌似有点鬼啊qaq。
    T2这什么鬼题目啊,出题人毒瘤吧。
    T3看一眼数据范围感觉像是(FWT),然后就(yy)了一个很有道理的(O(sum k_i+m2^m))做法。一发过大样例。
    然后滚回去写T1,倒是一下子就写完了,也没怎么(debug)就过了样例。预估(75)分。
    T2写了个退火,就是完全随机乱走的那种。
    下考前意识到没算退火的时间复杂度,心想着算了算了反正这题也是没分的就没管了。
    预估得分(75+0+100=175),实际得分(65+8+100=173)
    T1构造转移矩阵的时候写的是=1而不是++然后(sum|s_i|=0)的点就(G)了。
    然后T2(spj)出锅,喜闻乐见.jpg

    总结

    T1的复杂度是假的这我能说什么。
    T2的正解是假的这我能说什么。
    T3全场艹标算这我能说什么。

    简要题解

    kill

    对所有不合法串构造(AC)自动机,然后在一些禁止节点上打上标记,(dp)即可。
    考虑动态修改还要区间查询,所以用矩阵实现(dp)转移,用线段树维护区间矩阵乘积。禁止节点在(dp)中是没有任何意义的,所以把除禁止节点外的所有节点重新标号再做矩阵乘法,复杂度(O(qlog n(sum s_i-m)^3))。能过。

    plitics

    eat

    考虑枚举选出了(k)个拼盘后或起来的结果,一共是(2^m)种状态。因为我们可以算出每一种状态的价值,所以我们只关心每一种状态被构造出来的方案数。
    (f_i)表示是(i)集合的子集的集合数量,那么(g_i=inom{k}{f(i)})即表示选出(k)个盘子或起来集合是(i)的子集的方案数。
    那么只要求出(f_i),算出(g_i)再想办法还原回去就好了。
    显然是可以(FWT)的吧,复杂度不算读入是(O(n+m2^m))
    所以说这题的复复杂度瓶颈实际上在读入。

    不过大家写的貌似普遍都是,利用期望的线性性,对每一位分别考虑,然后复杂度就是(O(m))的,非常优秀。

    感觉(std)的做法比较像bzoj3771Triple这道题的加强版,就是大力容斥,然后利用系数是带符号第一类斯特林数的性质做到(O(km2^m))

    落实情况

    题目 kill plitics eat
    完成情况 corrected corrected? corrected
  • 相关阅读:
    [再寄小读者之数学篇](2014-07-17 一阶中值)
    对流体力学做出巨大贡献的杰出历史人物
    理科生毁灭世界
    [再寄小读者之数学篇](2014-07-17 行列式的计算)
    [再寄小读者之数学篇](2014-07-16 高阶导数的一个表达式)
    [再寄小读者之数学篇](2014-07-16 与对数有关的不等式)
    [再寄小读者之数学篇](2014-07-16 凹函数与次线性性)
    [再寄小读者之数学篇](2014-07-16 二阶中值)
    [再寄小读者之数学篇](2014-07-16 任意阶导数在零处为零的一个充分条件)
    对PostgreSQL xmin的深入学习
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9211103.html
Copyright © 2020-2023  润新知