<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[zpf1998的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/zpf1998</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; zpf1998]]></copyright><item><title><![CDATA[区间dp模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/122767264</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/122767264</guid><author>zpf1998</author><pubDate>Sun, 10 Apr 2022 22:15:32 +0800</pubDate><description><![CDATA[区间dp模板
区间dp可以分为几类分支。环形区间dp，区间dp记录方案数，区间dp和高精度结合，二维区间dp
环形区间dp
1068. 环形石子合并


]]></description><category></category></item><item><title><![CDATA[状压dp -- 状态压缩dp]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/122764193</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/122764193</guid><author>zpf1998</author><pubDate>Sat, 09 Apr 2022 17:09:01 +0800</pubDate><description><![CDATA[状态压缩dp
状态压缩dp 分为两种，一种是棋盘式，也叫做基于连通性，基础题是291. 蒙德里安的梦想，另一种是集合形式的，基础题目是最短Hamilton路径。
连通性状压dp
一般讲棋盘按照行或者列分开考虑，可以先算出单行状态下的合法状态，然后下一行的合法状态受上一行的状态影响，所以可以有关系矩阵表示f(a,b)是否合法，再进行dp的转移方程。
例题
AcWing 1064. 小国王
AcWing 327. 玉米田
AcWing 292. 炮兵阵地
集合覆盖
例题
AcWing 524. 愤怒的小鸟
Ac]]></description><category></category></item><item><title><![CDATA[树状数组模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/121680688</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/121680688</guid><author>zpf1998</author><pubDate>Mon, 06 Dec 2021 12:26:16 +0800</pubDate><description><![CDATA[树状数组模板
基本原理
基础功能 单点更新，区间查询

快速求前缀和 O(log(n))
修改某一个数字 O(log(n))
下面图片来自acwing的课程：


原始数据是A数组,用C(x)代表A[x-lowbit(x)+1,x]区间内的元素之和，然后用小矩形代替C(x)画图，C(x)覆盖范围就是他们的求和的范围, 下图中的数组可以形成一棵树，C(x)覆盖区间大小决定层高，红线代表上层可以由下层连线的部分求和得出。每一个点x都有儿子，儿子的数量是x-1的二进制组成中1的个数。
例如16(10000)的儿子]]></description><category></category></item><item><title><![CDATA[并查集模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/121610797</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/121610797</guid><author>zpf1998</author><pubDate>Thu, 02 Dec 2021 16:35:43 +0800</pubDate><description><![CDATA[并查集模板
用处
1.合并两个集合
2.查询某个节点的祖宗节点
优化
1.路径压缩，最坏情况 log(n)
2.按照秩合并，最坏log(n)
使用上面的两个优化后，时间复杂度O(alpha(n))
扩展
1.记录集合大小
集合大小绑定在根节点上，在合并的时候更新
2.每个点到根节点的距离
这个属性放在吗每个点上，例题：食物链（带权并查集(维护相对距离)，扩展域并查集(枚举所有可能性)）
3.链表染色
模板
在这里插入代码片

例题
AcWing 1250. 格子游戏 ： 并查集的应用之一，并查集判环

..]]></description><category></category></item><item><title><![CDATA[刷表法 和 填表法(DP)]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/121279681</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/121279681</guid><author>zpf1998</author><pubDate>Fri, 12 Nov 2021 00:58:21 +0800</pubDate><description><![CDATA[刷表法 和 填表法
在dp问题中，当我们写出了状态转移方程的时候，一般可以直接去迭代求解。
但是，与此同时有一个问题：例如 状态转移方程 是dp[i][j]=F{dp[i-1][j-1],dp[i-1][j],dp[i-1][j-1]} 这样的形态时，如何进行枚举呢？是枚举dp[i][j]，由dp[i-1][j-1],dp[i-1][j],dp[i-1][j-1]更新dp[i][j]，抑或是枚举dp[i-1][j-1]，去更新dp[i+1][j+1],dp[i+1][j],dp[i][j+1]。
填表法：可]]></description><category></category></item><item><title><![CDATA[动态规划 背包问题 模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/121002250</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/121002250</guid><author>zpf1998</author><pubDate>Mon, 08 Nov 2021 16:56:47 +0800</pubDate><description><![CDATA[背包九讲模板（部分）
背包九讲pdf资源
pdf下载
题目
题目链接第1-10题
01背包

 cin&gt;&gt;n&gt;&gt;m;
 for(int i=0;i&lt;n;++i){
        cin&gt;&gt;v&gt;&gt;w;
        for(int j=m;j&gt;=v;--j){
            f[j]=max(f[j],f[j-v]+w);
        }
    }


完全背包

    cin&gt;&gt;n&gt;&gt;m;
    fo]]></description><category></category></item><item><title><![CDATA[多重背包模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/111566829</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/111566829</guid><author>zpf1998</author><pubDate>Tue, 22 Dec 2020 20:59:35 +0800</pubDate><description><![CDATA[多重背包

#include&lt;iostream&gt;
#include&lt;cstdio&gt;
using namespace std;
const int maxn=2010;
int n,m;
int dp[maxn];

int main(void){
    cin&gt;&gt;n&gt;&gt;m;
    int v,w,s;
    for(int i=0;i&lt;n;++i){
        cin&gt;&gt;v&gt;&gt;w&gt;&gt;s;
        i]]></description><category></category></item><item><title><![CDATA[一般哈希 字符串哈希 hash]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/110954682</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/110954682</guid><author>zpf1998</author><pubDate>Fri, 11 Dec 2020 21:55:17 +0800</pubDate><description><![CDATA[一般哈希
来源： https://www.acwing.com/blog/content/404/
拉链法
拉链法，类似 图的邻接链表存储，对于一个对象x，算出对应的hash值k，将x存储在h[k]链表中
(1) 拉链法
    int h[N], e[N], ne[N], idx;

    // 向哈希表中插入一个数
    void insert(int x)
    {
        int k = (x % N + N) % N;
        e[idx] = x;
        ne[i]]></description><category></category></item><item><title><![CDATA[Trie树模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/110941969</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/110941969</guid><author>zpf1998</author><pubDate>Thu, 10 Dec 2020 13:10:46 +0800</pubDate><description><![CDATA[Trie树
是一种字符串集合组成的树状结构，可以与KMP结合，形成AC自动机

]]></description><category></category></item><item><title><![CDATA[KMP字符串 模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/110940932</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/110940932</guid><author>zpf1998</author><pubDate>Wed, 09 Dec 2020 21:56:20 +0800</pubDate><description><![CDATA[KMP
参考：https://www.acwing.com/solution/content/2286/
对于S中是否含有子串p这个问题, S，p起始都是1，不是0
暴力 的算法
同时引入了next数组简化计算，就是在对比时，如果对比失败，p数组不再是每次前进1格，而是跳跃性的前进，这其中利用了next数组的先验信息
所以每次匹配失败或者完全匹配，p的起始位置不是加1，而是跳跃性的变化，具体参考 j=next[j]
next数组
next数组用来存模式串中每个前缀最长的能匹配前缀子串的结尾字符的下标。 ne]]></description><category></category></item><item><title><![CDATA[双指针 离散化 区间融合 模板]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/110914560</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/110914560</guid><author>zpf1998</author><pubDate>Wed, 09 Dec 2020 11:17:45 +0800</pubDate><description><![CDATA[双指针
for (int i = 0, j = 0; i &lt; n; i ++ )
{
    while (j &lt; i &amp;&amp; check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类：
    (1) 对于一个序列，用两个指针维护一段区间
    (2) 对于两个序列，维护某种次序，比如归并排序中合并两个有序序列的操作


...]]></description><category></category></item><item><title><![CDATA[前缀和 差分 数组]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/110882136</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/110882136</guid><author>zpf1998</author><pubDate>Wed, 09 Dec 2020 01:31:58 +0800</pubDate><description><![CDATA[前缀和 差分
前缀和用于求解单点更新后区间的和，差分用于求解区间更新后区间内的单个元素
一维前缀和
将现有数组看作是数组a ,求解A的前缀和数组S
S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]

二位前缀和
S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)为左上角，(x2, y2)为右下角的子矩阵的和为：
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[]]></description><category></category></item><item><title><![CDATA[UVA - 1372 Log Jumpin 贪心]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/108469697</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/108469697</guid><author>zpf1998</author><pubDate>Tue, 08 Sep 2020 15:37:14 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-1372
分析
这道题我一开始一直认为时dp,最后可参考大佬的解法才发现时贪心问题
参考：https://blog.youkuaiyun.com/zstu_zlj/article/details/11881015
先按照起始点的大小从小到大排序，然后对于每个i，将它看作起始点，判断i+1是否可以加入进来
对于开始地第一个点，也就是cnt==1时，只要求xi[i+1]-xi[i]&lt;=k，就能将i+1加入进来，但是cnt&gt;1，就要求xi[i+1]]></description><category></category></item><item><title><![CDATA[UVA - 12235 Help Bubu 概率dp 状态压缩 记忆化搜索]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107930026</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107930026</guid><author>zpf1998</author><pubDate>Wed, 12 Aug 2020 12:37:42 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-11600
分析
概率dp，看到了N&lt;=30，想到了状态压缩，然后由于N比较大，而且状态中并不是所有状态都存在，所以使用map存储状态
对于M条边的处理，有两种办法，一种是用并查集，将连接起来的边连成一个集合，每次到下一个城市的时候，都去查看这个点的父节点和对应的 二进制的值（对应这个集合的所有点）
参考：https://www.cnblogs.com/jerryRey/p/4857941.html
或者将所有的联通点看作一个点，给这]]></description><category></category></item><item><title><![CDATA[UVA - 1407 Caves 树形dp 多重背包]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107897001</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107897001</guid><author>zpf1998</author><pubDate>Sun, 09 Aug 2020 17:45:25 +0800</pubDate><description><![CDATA[分析
参考：https://www.jianshu.com/p/065cfa72e24b
状态的定义比较明显，主要是状态转移部分有点复杂，差点被绕晕了，现在觉得类似于多重背包问题
//0-1背包的枚举物品
    for(int i=0;i&lt;g[node].size();++i){
        pair&lt;int,int&gt; &amp;temp=g[node][i];
        //为了放置重复计算，j从大到小进行更新
        for(int j=tot[node];j&gt]]></description><category></category></item><item><title><![CDATA[UVA - 1427 Paradev单调队列]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107891732</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107891732</guid><author>zpf1998</author><pubDate>Sun, 09 Aug 2020 15:11:03 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-1427
分析
这道题的状态是dp[i][j]，代表走到第i,j的位置时的收入v，采用填表法，到达i，j的选择有三种，一种是dp[i][j]=dp[i-1][j]，就是直接从上一行的第j个路口走到这一行的j路口,还有就是从左往右在i行走到j，或者从右往左，转移方程分别是   从左向右dp[i][j]=max(dp[i-1][k]+sum[i][j]-sum[i][k]) , k&lt;j ,sum[i][j]是从i行起点走到第j个路口的累计]]></description><category></category></item><item><title><![CDATA[UVA - 12260 Free Goodie]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107881742</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107881742</guid><author>zpf1998</author><pubDate>Sat, 08 Aug 2020 17:17:39 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-12260
分析
这道题的核心在于由于P采用贪婪的方法，所以它一定在前i个中至少占到一半左右的数量，所以d[i][j].value代表在J在前i个物品中占有了j个时候的最大价值，j&lt;=(i+1)/2，然后dp[i][j].loss代表了对于P的总价值造成的损失，设n个P的value之和为sum，P每次选择，都会对sum造成损失，如果损失最小，那么P的最终收益就会最大
状态转移过程有点类似于背包问题，每次都是选择或者不选最后一个物品
#]]></description><category></category></item><item><title><![CDATA[UVA - 662 Fast Food 区间dp]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107773508</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107773508</guid><author>zpf1998</author><pubDate>Mon, 03 Aug 2020 21:09:23 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-662
分析
和上一题UVA607很像，记录一下最优解的状态就行了，另外 区间【l，r】之间的最优点是(l+r)/2,这一点画图就可以看出来
代码
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;cmath&gt;
#include &lt;cstring&gt;
#include &lt;map&gt;
#include &lt;string&gt;
#incl]]></description><category></category></item><item><title><![CDATA[UVA - 607 Scheduling Lecture 线性dp]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107768864</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107768864</guid><author>zpf1998</author><pubDate>Mon, 03 Aug 2020 17:11:09 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-607
分析
这是一道线性dp,多出了一个需求，就是对应最少课程数的最少DI值，所以可以先求出最少课程数，顺便求对应的最少DI值，每次更新最少课程数时，或者相等时，考虑di值的变化
代码
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;cmath&gt;
#include &lt;cstring&gt;
#include &lt;map&gt;
#include ]]></description><category></category></item><item><title><![CDATA[UVA - 590 Always on the run]]></title><link>https://blog.youkuaiyun.com/zpf1998/article/details/107765461</link><guid>https://blog.youkuaiyun.com/zpf1998/article/details/107765461</guid><author>zpf1998</author><pubDate>Mon, 03 Aug 2020 15:46:12 +0800</pubDate><description><![CDATA[问题
https://vjudge.net/problem/UVA-590
分析
类似紫书上的例题UVA1025，记得使用转移代价矩阵记录代价，可以缩短查找的时间，时间可以倒推，也可以按照时间正序推
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;cmath&gt;
#include &lt;cstring&gt;
#include &lt;map&gt;
#include &lt;string&gt;
#include &lt;]]></description><category></category></item></channel></rss>