zoukankan      html  css  js  c++  java
  • [杂题合集] 其真无码耶?

    序列

    题目

    解法

    首先你会发现题目中神神叨叨的操作并没有什么渜用,实际上一个序列合法当且仅当权值和 (ge) $k imes $ 序列长度。

    (a) 求前缀和 (pre_i),这也等价于 (pre_r-rk-(pre_l-lk)ge 0) 时答案可为 (r-l)。二分序列长度可以做到 (mathcal O(nmlog n)),过不去。

    考虑对于特定的 (r),我们希望 (pre_l-lk) 尽量小,但这同时意味着 (l) 会更大。所以用双指针维护:从大到小枚举 (r),对于每个 (r) 维护最小的满足条件的 (l)。需要注意的是,(r) 的减小可能会导致 (l) 不再合法,但由于题目只要求最大的 (r-l),如果 (l) 再增大肯定不优,所以我们 “按兵不动,静候良机”。

    ( ext{CodeForces - 407E k-d-sequence})

    题目

    传送门

    解法

    懒了,直接贴学长的 ( m orz)

    ( ext{Minimal Power of Prime})

    预处理 (n^{frac{1}{5}}) 之内的质数,剩下的质数都 (>n^frac{1}{5}),所以不会超过 (4) 个。

    除了 (n=a^4,a^3,a^2),其它的最小值就都是 (1) 了。注意要先判断 (a^4),因为它会被 (a^2) 误判。

    ( ext{P1852 })跳跳棋

    (2) 年前竟然做过这题... 完全没有印象。

    考虑每种状态往里走的方式是固定的,当相邻棋子距离相同时无法移动。

    这很像一棵树!所有状态就是一个森林。

    设当前态为 (s),目标态为 (t)。首先判断它们是否在同一棵树。然后将它们挪到同样的深度,二分它们与 ( m lca) 的距离即可。

    考虑怎么加速 “跳” 这一 (mathcal O(d)) 的过程。考虑每次转向(方向即为最右棋子/最左棋子下标不变)区间长度至少减掉 (frac{1}{3}),所以转向复杂度可以承受,每个方向行走的距离推一推就行了。

    还有一个单 (log) 的做法:传送门

    ( ext{CodeForces - 1027D Mouse Hunt})

    每个点都是有出度的,这也就意味着每个点最后都会走到环上。

    贪心地想,我们在环上选最小值一定比在链上选更优。因为在链上选时,环上的点仍然无法到达,还会选择环上的最小值。注意,由于每个点只有一个出度,不会有环连着环这种难以判断的情况。

    感觉这个博主的实现很精细。其中 ( ext{mark[]}) 是因为一个连通块只有一个环,我们将环的值选了之后这个连通块都合法了,所以要整体标记,把没遍历的点也标记。

    ( ext{CodeForces - 985F Isomorphic Strings})

    我们将每个字母的出现位置进行哈希,查询时判断 (26) 个字母得出的哈希在数字上是否全等即可。

    ( ext{[HAOI 2008] })硬币购物

    首先做一个完全背包。考虑硬币数目非常小,我们可以枚举每种硬币 (i) 是否满足条件 (p_i) 然后进行大力容斥。

    具体就是满足 (p_i) 是硬币 (i) 购买个数超过 (d_i)。这样我们可以 钦定 满足 (p_i) —— 即 (dp_{s-(d_i+1)cdot c_i})。类似地,还可以 钦定 同时满足 (p_i)(p_j) —— 即 (dp_{s-(d_i+1)cdot c_i-(d_j+1)cdot c_j})

    ( ext{Cutting Plants})

    维护一个单调不增的双端队列,元素 (i) 表示将第 (i) 株植物砍成 (b_i) 的操作。

    • b[q.back()]<b[i]。队尾的操作不能操作在第 (i) 株上,所以后面也不行。
    • b[q.front()]>a[i]。队头的操作不能操作在第 (i) 株上,所以后面也不行。

    ( ext{A Magic Lamp})

    先开始的思路是令 (l=1,r=n),用 ( m st) 表找出最左边的最小值下标 (pos),如果删不了就将右边界缩小。但实际上这面临着一个问题:缩小之后由于前面不会删除一些下标,我们又可以选择这个最小值。

    更好的方法是先令 (l=1,r=m+1),这样保证不出现删不了的情况。接着转移到 (l=pos+1,r=r+1) 即可。

    ( ext{Heapsort})

    先正向考虑,如何才能最大化次数?第一次操作,必将把堆顶的 (n) 与堆底 (1) 交换。此时我们最好让 (1) 顺次向下交换,交换到 (n-1) 的位置,这样还能保证下一次操作 (1) 又到了堆顶。剩余的依此类推…

    倒着模拟,先把 (1) 放在堆顶(这相当于 (2-1)),接着将 (1) 经过路径的数向下移动。最后处理堆顶和当前堆底元素就完成了一次倒退。

    ( ext{Dist Max 2})

    首先考虑到二分 (k)。那么我们就需要找到一组 (i,j) 满足 (|x_i-x_j|ge k)(|y_i-y_j|ge k)

    可以考虑用一个特殊的队列维护:将 (x) 从小到大排序,插入 (i) 时,满足第一个条件的 (j) 被踢出队列,将 (j)(y) 值取 (max,min)

    ( ext{CF1354E Graph Coloring})

    (dp_{i,j}) 为前 (i) 个二分图,选了 (j)2 是否可行。这是 (mathcal O(n^2)) 的。

    考虑如何计算答案。由于每个二分图都一定选了一部,所以从 (dp_{cnt,tot_2}) 开始逆推,每次查询 (dp_{i-1,cur-b_{i,0}},dp_{i-1,cur-b_{i,1}}) 即可。

    ( ext{[BJOI 2016] IP})地址

    我们将 (mathtt{ip}) 拿来建一棵 ( m trie) 树。考虑树上两个节点 (i,j),其中 (i)(j) 的父亲。那么如果 (j) 节点有 (mathtt{ip}),被影响的节点只有终点为 (i)(fa_j) 的询问。

    类似线段树,添加 add 标记。当 (i) 做出更改时 (add_i) 加一,在修改和询问的过程中往下传,知道节点有 (mathtt{ip}) 的地方为止。

    ( ext{abc187E Through Path})

    巧妙的树上差分。对于修改 (u) 的子树的操作,可以直接在 (c_u)(k);反之,可以转化为在 (c_u)(k),整体再加 (k)。最后一次 ( m dfs) 即可。

    ( ext{CF1148E Earth Wind and Fire})

    首先可以将两个数列排序,(s_i) 最终要到达 (t_i)。考虑当两个石头的路径发生交叉时,它们本身可以交换。所以正确性保证。

    (delta_i=t_i-s_i),由于只有 (s_ile s_j) 时,(i,j) 才可以向里逼近,所以要求 (forall i,sum_{j=1}^i delta_jge 0)。具体可以用括号匹配来理解,(1) 相当于左括号,(-1) 相当于右括号。

    在计算答案时,用一个栈维护大于零的 (delta_i) 即可。每次配对一定会消耗一个数,总共只有 (n) 个数,所以种类数是 (n) 级别的。

    ( ext{CF1326E Bombs})

    由于答案是递减的,可以使用调整法。一个显著的好处是当 ( m check) 一个值 (x) 是否被炸时,我们无需判断比 (x) 大的数。

    考虑将 (ge x) 的数赋值为 (1),炸弹赋值为 (-1)。那么 (x) 被炸实际上就是对于任意位置都有 (suf_ile 0)(suf) 为后缀和)。考虑若存在 (suf_i>0),而 (>x) 的数字一定先牺牲,所以 (x) 就可以空出来。

    用线段树动态维护后缀和即可。

    ( ext{POJ - 3635 Full Tank?})

    题目描述

    一辆带有一个容量有限的油箱的车子在一张图上行驶,每行驶一单位长度消耗一单位油,图上的每个点都可以加油,不过都有各自的单位费用。
    (Q) 次询问,每次给出车的油箱的容量 (c),起点和终点,问从起点驾驶到终点的最少花费是多少。
    (Qle 100,cle 100,nle 1000,mle 10000)

    解法

    拆点,把原图的一个点 (i) 拆成 (c+1) 个点 ((i,j)),表示在 (i) 点油量为 (j)。按 "加油" 或 "开汽车" 转移。跑最短路即可。

    ( ext{usOJ - 9941})

    题目描述

    甲从 (A) 走最短路到 (B),乙从 (C) 走最短路到 (D)。每个时间可以走一步,或者等着。如果某个时间甲和乙在相同的点,就可以得一分,不过一个点上只能得一分。
    问最多可以得几分。
    (n≤50000,m≤200000)

    解法

    先将 (A ightarrow B,C ightarrow D) 的最短路上的点分别建成两个 ( m dag)。只保留在两个 ( m dag) 中的点和它们的边,求一个最长路。

    由于最短路中不可能有环,所以保证正确性。

    墨墨的等式

    首先可以差分一下,询问 ([0,w]) 区间内的答案。

    (delta)(a) 中的某个数,那么如果 (sum a_ix_i=r) 满足,(sum a_ix_i=r+kcdot delta(kin m N)) 也满足。如果枚举 (rin[0,delta)),求出满足 (sum a_ix_iequiv rpmod delta) 的最小值,那么与其同余的在 ([0,w]) 之间的解就可以 (mathcal O(1)) 地求出。

    由于此题 (n,a_i) 范围极小,我们可以考虑将其转化为图上问题:令 (dis_i) 为余数 (0) 到余数 (i) 的最短路。边数是 (ncdotdelta) 级别的,所以我们令 (delta=min a_i) 以减少边数。

    最后跑最短路即可。

    牛牛种小树

    一个结论是:无论给每个点分配多少度数((>0)),只要和为 (2n-2) 就一定可以构造出合法的树。

    考虑度数大于零的限制,我们先给每个点分配一个度数,这样就还剩 (n-2)。于是 (dp_i)(n-2) 度分配了 (i) 度的最大价值。转移时枚举给某个点拔高的度数,这样的点一定是存在的。

    时代的眼泪

    题目描述

    给定一棵树,对于 (iin [1,n]),输出

    [sum_{j eq i}sum_{xin P(j,i)} [w_x>w_j] ]

    其中 (w_i) 给定,(P(i,j))(i,j) 之间路径的点集。

    (nle 10^6,w_ile 10^9)

    解法

    这是一个换根 (mathtt{dp}),于是问题转化为求 ( m dfs) 序在某区间的点中权值严格小于 (v) 的点个数。

    这个可以用主席树维护,但是线段树常数过大。你会发现这个问题不涉及修改,于是可以往离线的方向考虑:从小到大枚举 (w),用一个数据结构维护 ( m dfs) 序,那么就天然满足 "权值严格小于" 的条件。

    具体地,用树状数组维护 ( m dfs) 区间内小于当前权值的点个数。我们就可以求出换根 (mathtt{dp}) 的变化量。

  • 相关阅读:
    centos下卸载rpm包
    centos下添加环境变量和启动apache
    centos(linux) 下如何查看端口占用情况及杀死进程
    如何使上层的div遮住的链接可以点击
    jquery.blockUI.2.31.js 弹出层项目介绍
    fieldset、legend、display html元素
    <a>标签中href="javascript:;"的意思
    memcache 学习笔记
    sublime text3 JS语法检测插件
    Apache Rewrite的主要功能
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15018802.html
Copyright © 2011-2022 走看看