zoukankan      html  css  js  c++  java
  • IOI2020国家集训队作业做题记录

    Part 1 1-50

    Part 2 51-100

    Part 3 101-150

    进度(33/50)

    (color{#FF003F}{ exttt {CF504E Misha and LCP on Tree}})

    序列上的问题可以二分+hash,直接上树。复杂度 (O((n+m)log n))
    评测链接

    (color{#FF003F}{ exttt {CF506C Mr. Kitayuta vs. Bamboos}})

    首先想到二分答案。

    让时间倒流,每个元素有个限制 (lim_i) 表示到某一轮 (a_i<=lim_i)
    每次操作变成 (lim_i-=a_i)(lim_i+=p),同时任意时刻都要有 (lim_i>=0),且最开始 (lim_i>=h_i)

    发现对于每个元素问题独立,于是分开做。
    搞个 (operatorname{map}) 维护下剩余的 (+p) 操作位置及数量,每次二分个位置使得 (lim_i<0),不断取大于这个位置且最小的 (+p) 操作即可。
    复杂度 (O((nlog m + mklog mk)log V))

    评测链接

    (color{#FF003F}{ exttt {CF512D Fox And Travelling}})

    首先可以发现环上的点不可能经过,这告诉我们要往树的方向去想。

    对图做类似拓扑排序的东西,出现过的点一定形成了一个森林。其中一些树有根,根是与未经过点相邻的经过了的点,可以证明根只有一个。树上的父子关系相当于是,如果取了一个点的所有儿子,才可以取这个点。

    对于有根树,通过简单dp处理出这棵树中取 (0..siz) 个的方案数。

    对于无根树,对所有点做一次dp,对应位上值相加。对于 (1leq i < siz),此时的根一定不选,对于 (i) 个点的方案被算了 (siz-i)次,所以 (dp_i/=siz-i)。对于 (i=siz),此时每个点都可以最后一个被选,不用除。

    做个背包合并。

    评测链接

    (color{#FF003F}{ exttt {CF516D Drazil and Morning Exercise}})

    (f_x=max_{i=1}^{n}dist(x,i))
    所有的 (f_x) 可以换根dp求出。

    问题转化成了:树上点有权值, (q) 次询问,给出 (L) ,求满足 (max_{i in S}f_i-min_{i in S}f_i leq L)(S) 中最大的集合大小。
    一种想法是每条边都有出现时间区间,线段树分治维护,复杂度 (O(nq log n alpha(n))) ,看起来很大的样子。

    考虑 (f_i) 的性质,如果把 (f_i) 最小的点作为根,(forall u=fa_v , f_v=f_u+w(u,v))

    证明:

    (g_i) 表示只考虑 (i) 子树中的点时的 (max dist(x,i)) ,有 (f_i geq g_i)

    首先先证 如果 (u)(f_i) 最小的点,(v)(u) 的儿子,那么 (f_v=f_u+w(u,v))

    假设 (f_v)(v) 子树内一点 (x) 转移,即 (f_v=g_v=g_x+w(x,v)),那么(f_u geq g_v+w(u,v) geq f_v),与 (u)(f_i) 最小的点矛盾,所以 (f_v=f_u+w(u,v))

    由上可知 (f_v=f_u+w(u,v) geq g_x+w(v,x)) ,那就有 (f_u+w(u,v)+w(v,x) > g_x),那么 (f_x=f_u+w(u,v)+w(v,x)=f_v+w(v,x))
    归纳一下就可知 (forall u=fa_v , f_v=f_u+w(u,v))

    把所有点按 (f_i) 从大到小的顺序加入,并查集维护下就行了。(O(n log n+nqalpha(n)))

    评测链接

    (color{#FF003F}{ exttt {CF521D Shop}})

    操作的顺序是123。把 (operatorname{assign}) 转化成 (operatorname{add}) ,再把 (operatorname{add}) 转化成 (operatorname{multiply})
    直接按顺序贪心取。

    评测链接

    (color{#FF003F}{ exttt {CF526F Pudding Monsters}})

    显然有(r-l<=max -min)。枚举左端点,单调栈维护最大最小值。只要如果全局 (max - min - r) 的最小值等于 (-l) ,就在线段树上数最小值个数。

    评测链接

    (color{#FF003F}{ exttt {CF526G Spiders Evil Plan}})

    先考虑单次询问。发现 (y) 条路径的端点一定是叶子节点,产生的联通块最多会有 (2y) 个叶子。但还是不好做。

    考虑一个相似的问题:一棵有根树,选 (k) 个点,最大化这 (k) 个点到根节点路径的并的大小。

    选的点肯定是叶子。如果 (k geq) 叶子个数,答案肯定是 (n)

    否则定义一个点的贡献为 (V_i)(i) 到根节点上没被经过的点的个数。每次选 (V_i) 最大的肯定最优。

    性质:每个点一定在其长链顶端的父亲所在长链底端的点被选后被选。

    那么 (V_i=dep_i-dep_{fa_{top_i}}),直接贪心。

    如果有多次询问,考虑优化上述做法的复杂度。
    有一个性质,直径的一个端点端点一定会被选中。
    不妨以直径端点为根,那么还要选 (2y-1) 个叶子。预处理下即可。

    考虑原问题。若直接用上述做法,可能 (x) 不在联通块内。

    有两种策略进行调整

    1. 删除第 (2y-1) 个点,加入 (x) 的子树内 (V_i) 最大的点。

    2. 找到 (x) 的祖先中离 (x) 最近的被覆盖的点,删除它子树中被选的一个叶子,加入 (x) 的子树内 (V_i) 最大的点。

    发现 (2) 策略不是很好维护。但是如果 (2) 策略比 (1) 策略优,那么 (x) 的祖先中离 (x) 最近的被覆盖的点的子树中只能有 (1) 个被选中的点。
    倍增往上跳即可。

    复杂度 (O((n+q)log n))

    评测链接

    (color{#FF003F}{ exttt {CF528C Data Center Drama}})

    条件每个点出入度都是偶数,得出每个点的度数是偶数,与欧拉回路有关。

    先说做法,把度数是奇数的点两两连边,如果总边数是奇数,再连个自环,跑欧拉回路,路径上的边隔一个反转。

    下面证明这是最优的。
    把度数是奇数的点两两连边是显然的。考虑直接跑欧拉回路,并且不反转边。我们称奇点是入度出度都是奇数的点,偶点是入度出度都是偶数的点。

    如果总边数是偶数此时图中有偶数个奇点,通过调整(反转一条边),可以使得点全是偶点,满足条件。

    如果总边数是奇数,此时图中有奇数个奇点,通过调整(反转一条边),可以使图中只剩下一个奇点,必须进行操作,加个自环即可。

    评测链接

    (color{#FF003F}{ exttt {CF536D Tavas in Kansas}})

    先跑最短路,每个人肯定是按 (dis) 从小到大取,设 A 的序列是 (t1),B 的序列是 (t2)
    由于总和不变,可以看成 (ans=A-B),A 要最大化 (ans),B 要最小化 (ans)

    这就可以 dp 了。
    (f_{i,j}) 表示 A 已经选了前 (i) 个,B 已经选了前 (j) 个,现在是 A 选,从这个状态到选完的答案。
    (g_{i,j}) 表示 A 已经选了前 (i) 个,B 已经选了前 (j) 个,现在是 B 选,从这个状态到选完的答案。
    (n^3) 转移是显然的。

    可以修改状态定义为
    (f_{i,j}) 表示 A 已经选了前 (i) 个,B 已经选了前 (j) 个,现在是 A 选且这一步 A 已经选了至少一个点,从这个状态到选完的答案。
    (g_{i,j}) 表示 A 已经选了前 (i) 个,B 已经选了前 (j) 个,现在是 B 选且这一步 B 已经选了至少一个点,从这个状态到选完的答案。
    考虑转移 (f_{i,j}) 可以转移到 (f_{i-1}{j})(g_{i,p}) ,其中 (p) 是第一个满足 (t2_p) 没在 (t1_{1..i}) 中出现过的位置,可以简单预处理求出。
    (g_{i,j}) 同理。
    于是就做完了。

    代码中 (t1,t2,f,g) 都是反的(指std::reverse()
    评测链接

    (color{#FF003F}{ exttt {CF538H Summer Dichotomy}})

    先不考虑 (t,T) 的限制,容易发现:如果有解,(n1=operatorname{max}L,n2=operatorname{min}R) 一定满足条件。
    加上 (t,T) 的限制,若 (n1+n2<t) 则增大 (n1),若 (n1+n2>T) 则减少 (n2)

    证明:

    1.当 (n1<=n2)
    此时线段两两相交。
    假设 (n1+n2<t),设 (cur) 为改变后的 (n1)
    (cur<=n2),则原来包含 (n1) 的线段仍包含 (n1),原包含 (n2) 的线段仍包含 (n2),条件仍满足。
    (cur>n2),因为当 (cur=n2) 时两者等价,必须一个不变,另一个增大(否则必然有不符合条件的),不妨使 (cur) 增大,故上述策略最优。
    (n1+n2>T) 的情况同理。

    2.当 (n1>n2)
    此时如果 (n1) 减小,则 (L=n1) 的线段不符合条件,所以 (n1) 只能增大。
    如果 (n2) 增大,则 (R=n2) 的线段不符合条件,所以 (n2) 只能减小。
    故上述策略最优。

    二分图染色搞搞。

    评测链接

    (color{#FF003F}{ exttt {CF547D Mike and Fish}})

    对于每一行,每一列建一个点,对于点 ((x,y)),在 (x)(y) 之间连边。

    显然,形成的图中如果点的度数都是偶数,那么根据欧拉路径定向,一定可以使得要求同一水平线或垂直线上两种颜色的数量相同。

    图中一定有偶数个奇数度的点,建一个虚点,向所有度数是奇数的点连边,根据欧拉路径定向,一定可以使得要求同一水平线或垂直线上两种颜色的数量最多相差 (1)

    评测链接

    (color{#FF003F}{ exttt {CF547E Mike and Friends}})

    (operatorname{parent tree})上线段树合并裸题

    评测链接

    (color{#FF003F}{ exttt {CF555E Case of Computer Network}})

    把边双缩点后是一棵树,对于每个要求树上差分做一下。

    评测链接

    (color{#FF003F}{ exttt {CF559E Gerald and Path}})

    (dp_{i,j,d}) 表示考虑了前 (i) 条线段,其中第 (j) 条方向是 (d),且第 (j) 条最靠右。

    如果 (i+1) 条线段,向右放置,那么直接转移 (dp_{i+1,*,*} leftarrow dp_{i,j,d}+ min(L_{i+1},P_{i+1,1}-P_{j,d}))
    一条线段向左放置的转移:枚举一个 (k) ,表示 (i+1)(k-1) 都向右,(k) 向左,(dp_{k,a,b} leftarrow dp_{i,j,d}+min(L_k,P_{a,b}-P_{j,d})+P_{a,b}-pos_k)

    正确性:所有转移都合法,且可以证明感性理解最优解一定能通过某种策略转移出来。

    评测链接

    (color{#FF003F}{ exttt {CF566C Logistical Questions}})

    不太懂,先鸽着,求教育(operatorname{/kel})

    评测链接

    (color{#FF003F}{ exttt {CF566E Restoring Map}})

    (f_u) 是距离 (u leq 2) 的集合。

    下面只考虑叶子节点数 (geq 3) 的情况。
    有个结论:若两点 (u,v) 满足 (|f_u cap f_v|=2),则交中的两个节点间有边,且所有连接非叶子节点的边都会出现。
    证明:
    1.(f_u) 一定是个联通块,(f_u cap f_v) 也是个联通块,两个点组成联通块所以两个点间有边。
    2.所有连接非叶子节点的边都会出现:分别取这两个点的任意一个邻居即可。

    所以我们可以先用 (operatorname{bitset}) 搞出所有连接非叶子节点的边。
    对于叶子节点,如果它 (f_u) 中的点的邻居集合与 (f_u) 相同,则这两点间有边。读者自证不难。
    同样用 (operatorname{bitset}) 优化。

    评测链接

    (color{#FF003F}{ exttt {CF568C New Language}})

    显然和 ( exttt{2-sat}) 有关。设输入中的串是 (s),答案串是 (t)

    假设我们知道了 (operatorname{lcp}(s,t)),那就可以按顺序枚举 (operatorname{lcp}(s,t)) 后每个位置放 (V) 还是 (C),暴力染色判断就行了。

    从大到小枚举 (operatorname{lcp}(s,t)),用 ( exttt{2-sat}) 判断是否可行即可。

    评测链接

    (color{#FF003F}{ exttt {CF568E Longest Increasing Subsequence}})

    考虑LIS问题的经典 (O(nlog n)) 解法,(dp_i=max_{a_j<a_i}(dp_j)+1)(operatorname{Fenwick tree}) 优化。

    回到本题,首先可以发现不重复选这个限制是没有意义的,因为重复选了对答案没有贡献。

    一种 naive 的想法是对每个空缺位枚举选哪个数,dp的同时用 (operatorname{Fenwick tree}) 维护数组 (maxval)(maxval_i=max_{dp_j}(a_j<=i))。复杂度是 (O(n log n + mklog n))。冷静分析一下发现瓶颈在每次都要更新 (maxval) 数组,又发现如果只在 (k) 个空缺位置暴力更新复杂度是对的。

    对于 (a_i=-1) 的位置,对 (maxval) 数组求前缀 (max),枚举当前位选了什么数,(dp_i=max_{j in S} maxval_{j-1}+1)

    对于 (a_i ot=-1) 的位置,(dp_i=maxval{a_{i-1}}+1),其中 (maxval) 有两部分,分别是 (a_i=-1)(a_i ot=-1)的贡献,同时维护 (operatorname{Fenwick tree})

    考虑如何构造方案,

    如果当前位不是空缺位,直接到 (dp) 时记录的最优转移点。

    否则 (a_i=max_{x in S,x<last}x) ,并尝试向前找到一个非空缺位且满足 (dp_j+1=dp_i (a_j<a_i)),如果没找到,就找离 (i) 最近的空缺位,递归地构造。

    容易证明这样一定可以构造出最优解。

    对于本做法有点卡常,需要精细地实现程序。复杂度 (O(nlog n + mk))代码

    评测链接

    (color{#FF003F}{ exttt {CF571D Campus}})

    考虑只有1,3,5操作,带权并查集可以快速维护,每次合并新建节点,路径压缩的时候把权值算一下。

    如果有2,4操作,那么离线下来,先做2,4,算出每个点最后被清空的时间,减一减。

    评测链接

    (color{#FF003F}{ exttt {CF573E Bear and Bowling}})

    考虑贪心

    定义每个点的贡献为 (k_i*a_i+suf_i) ,其中 (k_i) 表示位置 (i) 之前被选的数的数量,(suf_i) 表示位置 (i) 之后被选的数的 (sum a_i)
    每次选贡献最大的点,历史最大值就是答案。


    ( exttt { 证明 by } exttt {c} color{#FF003F}{ exttt {z_xuyixuan}})

    式子是个斜率优化的形式,想到分块维护凸壳,直接凸壳上二分的话,复杂度会带一个 (log),由于斜率具有单调性,单调队列搞搞就好了。

    评测链接

    (color{#FF003F}{ exttt {CF575A Fibonotci}})

    线段树维护矩阵乘法。

    评测链接

    (color{#FF003F}{ exttt {CF576D Flights for Regular Customers}})

    bitset优化矩阵乘法。复杂度 (O(frac{n^3m log d}{w}))

    评测链接

    (color{#FF003F}{ exttt {CF576E Painting Edges}})

    线段树分治。边查询边加入修改。

    评测链接

    (color{#FF003F}{ exttt {CF578E Walking!}})

    可以发现问题等价于将原串划分成尽量少的 (L,R) 交错的子序列。
    先贪心地划分,再考虑合并, 简 单 分类讨论即可。

    评测链接

    (color{#FF003F}{ exttt {CF582E Boolean Function}})

    建表达式树,FWT优化dp。

    评测链接

    (color{#FF003F}{ exttt {CF585E Present for Vitalik the Philatelist}})

    枚举集合的 (gcd),乘上与 (gcd) 互质的数的个数。这两个都莫比乌斯反演一下,反演出来是 (f_i=sum_{x|i}a_x) 的形式。

    直接调和级数搞搞,或者 (operatorname{Dirichlet}) 前缀和算下。复杂度 (O(Vlog V)) / (O(Vlog log V))

    评测链接

    (color{#FF003F}{ exttt {CF585F Digits of Number Pi}})

    (S) 的所有长度为 (lfloor frac d2 floor) 的子串建个 ACAM,数位dp。

    评测链接

    (color{#FF003F}{ exttt {CF587D Duff in Mafia}})

    二分答案+(operatorname{2-sat})

    评测链接

    (color{#FF003F}{ exttt {CF587F Duff is Mad}})

    考虑如何暴力,建 (operatorname{ACAM}),查询一个点在 (operatorname{trie}) 树上到根的路径上的所有点在 (operatorname{fail}) 树上到根节点中满足 (l leq id leq r) 的总和。

    有两种做法。
    1.对一个点在 (operatorname{trie}) 树上到根的路径上的所有点打标记,在 (operatorname{fail}) 树上算子树和,统计答案。单次可以处理关于这个串的所有询问,复杂度 (O(sum len+n))

    2.对一个点在 (operatorname{trie}) 树上到根的路径上的所有点计算其在 (operatorname{fail}) 树上到根的答案,数据结构维护。单次可以一个询问,复杂度 (O(len))

    其中 (2) 方法也等价于把 (l,r) 中的点在 (operatorname{fail}) 树上做子树加,查询一个点在 (operatorname{trie}) 树上到根的路径上的所有点的权值和。

    考虑根号分治。
    对于 (lenleq S) 的串用 (2) 方法,对于 (len>S) 的串用 (1) 方法。

    如果 (2) 方法中的数据结构使用 (operatorname{Fenwick tree}) ,复杂度 (O(nsqrt{nlog n}))

    如果 (2) 方法中的数据结构使用 (O(sqrt n)) 区间加,(O(1)) 单点查询的分块 ,复杂度 (O(nsqrt{n}))

    评测链接

    (color{#FF003F}{ exttt {CF603E Pastoral Oddities}})

    结论:一个图合法,当且仅当每个连通块的大小都是偶数。
    证明:

    必要性:度数的奇偶性,读者自证不难。
    充分性:
    下面只考虑图连通的情况。
    (n=2) 时,显然成立。
    (n>2)(n) 是偶数时,假设 (n-2) 成立,加入两个点。

    如果两个点间有边,不取这两个点与原连通块间的边,取两点之间的边即可;
    如果两个点间无边,将原连通块中与这两个点相连的点之间的边不取,取这两点与原联通块的边即可。

    归纳可证原命题成立。

    简单 (LCT) 维护。

    评测链接

    (color{#FF003F}{ exttt {CF605E Intergalaxy Trips}})

    先说做法。
    (E_x) 表示到目前为止的答案,显然 (E_x) 不会从更大的地方转移。(E_x = sum_{i}E_iP_{x,i}prod_{j<i}(1-P_{x,j}))
    直接做的话,问题在于你不知道 (E) 的大小关系。考虑动态维护,每次找个答案最小的点,显然它不会被其他点更新,用它去更新其他点,复杂度是 (O(n^2))

    每次 (E_x) 并不是真实的答案,可能与它的每条边都不存在,要除 (1-prod_i (1-P_{x,i}))

    唯一需要证明的地方是 (E_x = sum_{i}E_iP_{x,i}prod_{j<i}(1-P_{x,j})),可能还有一种策略是并不全选比 (E_x) 小的,只选较小的几个。

    证明:

    假设 (x) 已经从若干个点处转移,现在考虑加入 (i) 点,满足 (frac{E_i}{1-prod_{j}(1-P_{i,j})}leq frac{E_x}{1-prod_{j}(1-P_{x,j})})

    (P=P_{x,i},M=prod_{j}(1-P_{x,j}),C=frac{E_i}{1-prod_{j}(1-P_{i,j})},0leq P,Mleq 1)

    满足的条件是 (Cleq frac{E_x}{1-M})

    原答案是 (frac{E_x}{1-M}),加入后答案是 (frac{E_x+C*P*M}{1-M+M*P})

    需要证明 (frac{E_x+C*P*M}{1-M+M*P}leq frac{E_x}{1-M})

    (ecause Cleq frac{E_x}{1-M} leqfrac{E_x}{1+M})

    ( herefore C+C*Mleq E_x)

    ( herefore C*M*P+C*M^2*Pleq E_x*M*P)

    两边同时加 (E_x-E_x*M)(E_x-E_x*M+C*M*P+C*M^2*Pleq E_x*M*P+E_x-E_x*M)

    整理得:((E_x+C*P*M)*(1-M)leq E_x(1-M+M*P))

    ( herefore frac{E_x+C*P*M}{1-M+M*P}leq frac{E_x}{1-M})

    所以加入 (i) 更优。

    而显然从期望答案更大的点转移是不优的,所以最优策略是从答案比 (x) 小的所有点转移。

    评测链接

    (color{#FF003F}{ exttt {CF611G New Year and Cake}})

    设点集为 (p_{1..n})(逆时针)。答案等于 总面积*(n(n-3)-)每种方案中较小的那块的面积*(2)

    可以用 (operatorname{two-pointers}) 对于每个点算出满足 面积<=总面积/2 的最远的点,设它是第 (k) 个点。
    考虑如何快速计算确定了 (k) 时的答案。

    [egin{aligned} ans&=sum_{j=i}^{k}S(p_{i..j})\ &=sum_{j=i}^ksum_{t=i}^{j-1}(vec{p_t}-vec{p_i}) imes (vec{p_{t+1}}-vec{p_i})\ &=sum_{j=i}^ksum_{t=i}^{j-1}(X_t-X_i)*(Y_{t+1}-Y_i)-(Y_t-Y_i)*(X_{t+1}-X_i)\ &=sum_{j=i}^ksum_{t=i}^{j-1}vec{p_t} imes vec{p_{t+1}} + X_i*(Y_t-Y_{t+1}) - Y_i*(X_t-X_{t+1})\ &=sum_{j=i}^k(-vec{p_i} imes vec{p_j}+sum_{t=i}^{j-1}vec{p_t} imes vec{p_{t+1}})\ end{aligned} ]

    简单预处理即可,复杂度 (O(n))

    评测链接

    (color{#FF003F}{ exttt {CF626G Raffles}})

    显然的贪心:每次取使答案最大的。可用堆做到 (O(tlog n))
    可以证明,每次修改后,策略最多只会变化 (1) 次。(读者自证不难)
    用两个堆即可维护。

    评测链接

  • 相关阅读:
    (转载) mysql中,option是保留字段么?
    (转载)腾讯CMEM的PHP扩展
    (转载)一句简单命令重启nginx
    (转载)四种常见的 POST 提交数据方式
    (转载)完美解决PHP中文乱码问题
    (转载)file_get_contents("php://input")
    (转载)PHP 下 CURL 通过 POST 提交表单失败的原因之一与解决办法
    (转载)php array_merge 和 两数组相加区别
    Immutable-不变模式与不变类
    zookeeper 编程框架 curator
  • 原文地址:https://www.cnblogs.com/Frame233/p/12524393.html
Copyright © 2011-2022 走看看