八点五省联考 2018

一双木棋

状态数不多,直接爆搜

https://loj.ac/s/1676274

IIIDX

考虑依次给 \(i=1,2,\cdots,n\) 填上数,每次尽量填最大的。考虑什么时候 \(i\) 填上 \(x\) 是合法的。考虑 Hall 定理,发现左部点约束最严的时候肯定是找一个已经填过的点 \(u\),然后对所有 \(d_v\ge d_u\)\(v\),选出 \(v\) 的子树内的所有点,也就是说我们会选一个后缀的子树的并。形式化地,对每个已经填过的点 \(u\),所有 \(d_v\ge d_u\)\(v\) 的子树内未填的点并起来的大小不能超过 \(\ge d_u\) 且尚未被填入的格子个数。

维护 \(w_i\) 表示如果在判定中选择分界点为 \(i\)\(\ge i\) 的剩余空位数减去所有 \(d_u\ge i\) 的子树并中未填点数的差,那么当前状态合法当且仅当 \(w_i\ge 0\) 对所有 \(i\) 成立。

考虑给 \(u\) 填入 \(x\) 有什么影响,发现对前一项的影响是所有 \(i\le x\)\(w_i\leftarrow w_i-1\)。考虑后一项会发生什么变化,我们发现由于树的 BFS 序就是 \(1,2,\cdots,n\),因此 \(u\) 的子树内一定完全是空的,祖先一定是满的。因此,设 \(v\)\(u\) 的父亲,显然只有 \(i\le x\)\(w_i\) 会发生改变,具体地:

  • \(i \le d_v\) 时这个子树并中未填的点的个数会 \(-1\),导致实际的 \(w_i\) 不改变;
  • \(d_v<i\le x\) 时,子树并会多出 \(\text{size}_u-1\),导致实际的 \(w_i\) 的变化为 \(w_i\leftarrow w_i-\text{size}_u\)

因此,实际的影响就是:对所有 \(d_v<i\le d_u\),令 \(w_i\leftarrow w_i-\text{size}_u\)。那么要想维持 \(w_i\ge 0\),就只需要找到 \(d_v\) 后面的最大的 \(x\),使得对 \(i\in (d_v,x]\),均有 \(w_i\ge \text{size}_u\),然后将这个区间都减去 \(\text{size}_u\)。线段树维护即可,时间复杂度 \(O(n\log n)\)

https://loj.ac/s/1878987

秘密袭击

考虑对每个 \(x\) 算出第 \(k\)\(\ge x\) 的方案数,这个就是对每个点 \(i\) 如果 \(d_i\ge x\) 就把他的权值设为 \(1\), 否则权值为 \(0\),那么第 \(k\)\(\ge x\) 相当于是说这个连通块里至少有 \(k\)\(1\)

直接 DP,复杂度是 \(O(n^3)\)\(n=1666\),而且还开 5s,这不是稳过?过了,好像 2s 都不到。。

https://loj.ac/s/1879374

我去。。怎么正解是 \(O(n^2\log n)\),有点猛了

简单写一下题解做法:考虑设 \(f_{u,i,j}\) 表示选一个以 \(u\) 为根的连通块,使得其中 \(\ge i\) 的点有恰好 \(j\) 个的方案数。那么答案就是 \(\sum_{u,i}\sum_{j=k}^{n}f_{u,i,j}\)

\(F_{u,i}(x)\) 为其生成函数,我们考虑 DP 是咋做的,发现会先把所有 \(p\ge a_u\)\(f_{u,p,1}\leftarrow 1\),所有的 \(p<a_u\)\(f_{u,p,0}\leftarrow 1\)。然后接下来枚举儿子 \(v\),让所有 \(F_{u,p}\leftarrow F_{u,p}\times(F_{v,p}+1)\)

直接维护多项式当然很寄,考虑插值:取点值 \(t\),发现我们的操作对 \(F_{u,i}(t)\) 的影响是:

  • 令一个区间内的 \(f_{u,p,1}\leftarrow 1\):令所有的 \(F_{u,p}(t)\leftarrow t\)
  • 令区间内的 \(f_{u,p,0}\leftarrow 1\)\(F_{u,p}(t)\leftarrow 1\)
  • \(F_{u,p}\leftarrow F_{u,p}\times(F_{v,p}+1)\):先在对面全局 \(+1\),然后对应点值相乘。

线段树合并维护即可。只需要维护区间加,区间乘。然后我们考虑最终直接对着所有 \(F_{u,i}\) 之和去插值(也就是对这个总和多项式插值),那也就是要再多维护一个区间和。

做一次的复杂度是 \(O(n\log n)\),插值做 \(n\) 次就是 \(O(n^2\log n)\)。最后插回来系数就行了。

实际上貌似也可以直接做 DFT 然后直接在线段树上维护多项式点乘和多项式的求和,复杂度应该是不变的!

然后你再想想发现维护 DFT 其实就是维护单位根出的点值。。没区别的!!

劈配

考虑 \(C=1\) 怎么做,发现这个时候每个人的选择是唯一的,我们可以直接 \(O(nm)\) 算一轮,对于第二问就直接二分,复杂度是 \(O(n^2m\log n)\)

那么 \(C>1\) 怎么办呢,这个时候问题在于某些人可能有多种选择,而他的多种选择可能带来不同的结果。一种想法是类似二分图匹配的匈牙利算法,我们对每个人从大往小枚举他可能的候选导师,如果当前这个导师已经满员了,我们尝试找这个导师的一个学生,让他再去换一个别的导师。

考虑仿照匈牙利算法,依次考虑每个人 \(x\),发现他能匹配上导师 \(y\) 当且仅当 \(y\) 能够通过当前的残量网络到达一个没有满的导师。我们找到符合条件的 \(y\) 中志愿最靠前的一个即可。

我们在每轮增广后 BFS 算出每个点能否到一个没有匹配满的导师即可。那么这部分的时间复杂度还是 \(O(nm)\)。进一步你发现二分都不需要了,我们在尝试加入 \(i\) 的时候直接顺便把别的都算了就行。复杂度是 \(O(n^2m)\)

https://loj.ac/s/1880397

林克卡特树

没看题解切的(但是这个也太经典了吧??

相当于选 \(k+1\) 条点不相交的路径,最大化点权和。

wqs 二分,然后 DP 的时候记录 \(f_u\) 表示 \(u\) 点的答案,\(g_u\) 表示考虑 \(u\) 点的子树,要求存在一个以 \(u\) 为端点的链时候的答案,那么转移就是:

  • \(f_u\) 有三种情况,第一种是直接所有儿子的 \(f_v\) 加起来,第二种是选择一个儿子 \(x\),用其他儿子的 \(f\) 之和加上 \(g_x+w(x,u)\) 来更新答案,第三种是合并两条链,这种情况还需要加上一个二分的斜率 \(m\),因为链的总数少了一条。
  • \(g_u\) 可以直接选自己这个单点作为转移点,这种情况下是所有儿子的 \(f\) 之和减去 \(m\),另一种方法是选一个儿子 \(x\) 然后用 \(g_x+w(x,u)\) 加上其他儿子的 \(f\) 之和更新答案。

然后为了要 wqs 还得记录选了多少条,那就记录 \(\textit{cf}_u,cg_u\) 分别表示最优情况下选的链的个数,如果有多解选尽可能多条,最终会选多少。这也是容易转移的。

总复杂度 \(O(n\log V)\)。本来想先写个暴力 \(O(\sum \deg^2)\) 转移试试,结果直接过了,惊讶

https://loj.ac/s/1880823

制胡窜

没看题解切的

用总的减去不合法的。考虑不合法的怎么算。

考虑在 SAM 上定位到询问串 \(t=S[l\cdots r]\),记 \(L=r-l+1\),相当于要切两刀割开所有字符串。

找到 endpos 集合中的最大值 \(m\),那么后一刀切的位置 \(p\) 需要满足 \(p\in[m-L+1,m-1]\)。这里在 \(p\) 处切一刀表示分开 \(p,p+1\) 两个位置,即取 \(i=p\)\(j=p+1\)

如果在靠后的那一刀的位置是 \(p\),那么接下来我们应当找到 \(\le p\) 的 endpos 中的最大值 \(y\) 和最小值 \(x\),然后把答案加上 \(|[x-L+1,x-1]\cap[y-L+1,y-1]|\)。如果所有 endpos 都 \(>p\) 那下一刀可以随便切,方案数是 \(p-1\)。这种情况能发生当且仅当所有 endpos 的交非空。

形式化地我们设 \(f(p)\) 表示 \(\le p\) 的最大的 endpos 位置,\(nx(p)\) 表示 \(>p\) 的最小 endpos 位置,那么 \(f(p)=y\) 当且仅当 \(nx(y)>p\ge y\),那么答案就是

\[\sum_{p=m-L+1}^{m-1}\max(x-1-f(p)+L,0)\\ \]

交换求和顺序,枚举 \(f(p)\) 得到

\[\sum_{y\in\text{endpos}(t)}|[x-L+1,x-1]\cap[y-L+1,y-1]|\times|[y,nx(y)-1]\cap[m-L+1,m-1]| \]

我们仔细地写一下限制,前一条是说 \(y-L+1\le x-1\),后一条需要 \(m-L+1\le nx(y)-1\),两条都满足之后方案数就是 \((x-1-y+L)\times (nx(y)-1-\max(m-L,y-1))\)。这里当 \(y\) 是最大值的时候我们认为 \(nx(y)=n+1\);同时还需要特判一下所有 endpos 都有交的情况,大概是一个二次函数。

首先由 \(y-L+1\le x-1\) 得到的关于 \(y\) 的限制是一个前缀,由 \(m-L+1\le nx(y)-1\) 得到的限制是一个后缀,交一下就是一个区间 \([l,r]\)。然后大概还需要对 \(y\le m-L+1\)\(y>m-L+1\) 分类讨论。

先考虑 \(y\le m-L+1\),我们拆出 \(1,y,nx(y),y\times nx(y)\) 相关的四项,答案就是

\[(x+L-1)(L-m-1)\times\sum 1\\+(m-L+1)\times\sum y\\+(x+L-1)\times\sum nx(y)\\ -\sum nx(y)\times y \]

然后再考虑 \(y>m-L+1\)。这个时候答案是 \((x-1-y+L)\times(nx(y)-y)\),拆一下就是

\[-(x+L-1)\times \sum y\\ +(x+L-1)\times\sum nx(y)\\ +\sum y^2\\ -\sum y\times nx(y) \]

那就是要维护区间内的 \(\sum y,\sum nx(y),\sum nx(y)\times y,\sum 1\)。先离线然后在 parent 树上跑线段树合并就行了,线段树需要支持查询区间个数,区间和,区间邻项乘积和,区间平方和,以及 lowerbound。然后为了定位到这个节点,大概还需要在 parent 树上倍增。

具体来说我们线段树维护区间内 endpos 的个数以及 endpos 位置的和,然后还要实现一个 lowerbound,那么要查询区间 \([l,r]\) 内的 \(\sum nx(y)\) 就先找到 \(\ge l\) 的第一个 endpos 中的位置 \(p\),再找到 \(>p\) 的第一个位置;在 \(r\) 那边我们也这么做一遍,然后再查询这个新区间内的 \(\sum y\)

\(\sum y\times nx(y)\) 也是类似的。考虑线段树合并咋维护 \(\sum y\times nx(y)\),发现只需要多维护 \(L(p),R(p)\) 表示区间内最左端和最右端的 endpos 位置就行了。定位这个节点相当于在 parent 树上找一个最深的祖先 \(a\) 使得 \(\text{maxlen}_a\ge L\),那就直接倍增就行了。总的复杂度是 \(O((n+q)\log n)\)

写吐了

https://loj.ac/s/1881251

posted @ 2023-10-11 15:51  云浅知处  阅读(127)  评论(0编辑  收藏  举报