
数据结构
Lupin123123
这个作者很懒,什么都没留下…
展开
-
HDU - 7072 双端队列+对顶
题目链接对顶双端队列。从左边插入就插入到左边的deque中,从右边插入就插入到右边的deque中,并在这个过程中维护lsize=rsize或lsize+1=rsize。tips:这个对顶的处理在处理在 这道题 中也用到了。#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define INF 0x3f3f3f3ftypedef long long ll;co原创 2021-09-13 00:37:26 · 152 阅读 · 0 评论 -
[hdu] P6964 I love counting
树状数组+trie树。原创 2021-08-14 03:50:46 · 299 阅读 · 0 评论 -
[ZOJ] P3228 Searching the String
ac自动机练手题,可以当成ac自动机不重叠匹配的模板。 题目链接由于有多个模式串要匹配,那么如果用kmp复杂度就是O(qn)O(qn)O(qn),这显然是吃不消的。那么就考虑用多模式串匹配的利器——ac自动机。时间复杂度接近O(n)O(n)O(n)。对于这道题要解决的第一个问题是如何实现不重叠匹配。思考后不难发现,只需记录trie图中的结点所表示的单词上一次在文本串中出现的位置即可。具体表现为下面的代码: void match2(char *s) //不可重叠 { int len=strle原创 2021-08-13 19:43:36 · 133 阅读 · 0 评论 -
[学习笔记] KMP算法
KMP算法可以O(n)O(n)O(n)的时间内实现模式串与文本串匹配,而strstr的朴素方法要O(n2)O(n^2)O(n2)如果要在s1中对s2匹配,先看看朴素方法: for (int i=1; i<=strlen(s1+1); i++) { int flag=1; for (int j=1,k=i; j<=strlen(s2+1); j++,k++) { if (s1[k]!=s2[j]) { flag=0; break; } }原创 2021-08-12 23:22:06 · 128 阅读 · 0 评论 -
[Luogu] P1083 [NOIP2012 提高组] 借教室(差分)
一开始用线段树做的,后来还听说能二分+差分?!这个做法真挺巧妙的。原创 2021-08-11 23:51:41 · 120 阅读 · 0 评论 -
[Luogu] P1083 [NOIP2012 提高组] 借教室(线段树)
题目链接最小值线段树模板题。按顺序更新区间,维护最小值。最小值小于0的时候就找到矛盾了。复杂度O(mlogn)O(mlogn)O(mlogn)完整代码:#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define INF 0x3f3f3f3ftypedef long long ll;const int maxn = 1e6+5;using namesp原创 2021-08-11 22:32:44 · 123 阅读 · 0 评论 -
[hdu多校] Lawn of the Dead
没看数据之前,第一想法是dp,复杂度O(mn)。看了数据后意识到这种想法是不行的,但是没关系可以借助dp的思想。能到达一个点,就到能到达他的左边或到达上面,进一步逐行考虑,就是要判断能否到达这个点的上面。如下图所示:这种思想还是很重要的,一行一行的看,从无序变有序类似的思想在P1985 [USACO07OPEN]翻转棋 Fliptile S中也有体现。标记的操作要用线段树完成,这边要开两个线段树,分别表示当前要处理的行和前一行。query操作表示查询要查询区间的子区间的最靠左的一个端点。#in原创 2021-07-30 15:59:23 · 237 阅读 · 0 评论 -
带括号的四则运算计算器
栈的应用,思想比较容易,代码实现起来还是比较烦的,尤其是处理括号的时候。不过确实锻炼coding的能力。大致思路:1.开两个栈,一个符号栈,一个数字栈。2.从头到尾遍历整个字符串,遇到运算符就把紧挨这个运算符的数字加到数字栈中,计算运算符之前的结果。遇到’(‘就直接放入符号栈,遇到’)‘就出栈到’('为止。具体代码:#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0原创 2021-08-08 13:39:16 · 1491 阅读 · 1 评论 -
[模板] 后缀数组
int n,m;int height[maxn];char s[maxn];int rak[maxn],sa[maxn],tp[maxn],tax[maxn];void bucket() //桶排序{ for(int i=0; i<=m; ++i) tax[i]=0; for(int i=1; i<=n; ++i) tax[rak[i]]++; for(int i=1; i<=m; ++i) tax[i]+=tax[i-1]; for(int i=n; i>=1原创 2021-07-31 22:14:13 · 83 阅读 · 0 评论 -
[Luogu] P1122 最大子树和
直接d[x]+=max(0,dp[son]),但是答案不一定是dp[root],因为根节点不一定会被选上,要中途记录最大值。#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define INF 0x3f3f3f3ftypedef long long ll;const int maxn = 2e5+5;using namespace std;int n,r原创 2021-08-05 00:38:56 · 125 阅读 · 0 评论 -
[Luogu] P2014[CTSC1997] 选课
思路:(跟[Luogu] P2015 二叉苹果树几乎一模一样)1.建一棵有根树,因为每门课有一门或没有直接先修课,所以父亲是先修课2.树上dp,转移方程dp[x][j]=max{dp[x][k]+dp[son][j-k]}dp[x][j]表示在以x为跟的树上选j个点所能获得的最大值tips:由于父节点是先修课,所以在以x为跟的树上选j个结点,j>1时根节点必须选择,即dp[x][j]不能从dp[x][0]+dp[son][j]转移过来具体体现为下面的代码片段#include<bits原创 2021-08-04 23:53:19 · 151 阅读 · 0 评论 -
[Luogu] P1040[NOIP2003 提高组] 加分二叉树
思路:因为中序遍历已知,所以找到根以后就可以递归的处理问题了。定义dp[i][j]表示中序遍历i到j的子树的最大加分,那么dp[i][j]=max{dp(l,k-1)*dp(k+1,r)+dp[k][k]},然后可以记忆化搜索。#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define INF 0x3f3f3f3ftypedef long long ll;c原创 2021-08-04 22:51:31 · 125 阅读 · 0 评论 -
[Luogu] P2015 二叉苹果树
#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define INF 0x3f3f3f3ftypedef long long ll;const int maxn = 1e5+5;using namespace std;int n,q;int dp[1001][1001],w[maxn],size[maxn];int cnt,head[maxn];st原创 2021-08-04 18:44:02 · 136 阅读 · 0 评论 -
[模板] 树的直径
以POJ - 2631为例,求树的直径和路径上的点#include<bits/stdc++.h>#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#define INF 0x3f3f3f3ftypedef long long ll;const int maxn = 1e5+5;using namespace std;int cnt,head[maxn];struct e{ int to; int原创 2021-08-04 15:33:12 · 220 阅读 · 0 评论 -
[Luogu] P5546 公共串
题意:求n个字符串的最长公共子串思路:后缀数组+二分1.若是求两个字符串的最长公共子串的长度且两字符串不太长本可以用dp2. 因为后缀数组方便处理子串问题,所以可以将问题转化成特殊的子串问题。所以将若干字符串拼成一个字符串s,并记录这个长串的每一部分属于哪个短的字符串。3. 但是这跟求子串的最长重叠长度不同,子串是“分组”的。所以将各个子串连接的时候要用“特殊”的连接符。4. 所求的不是具体的串而是长度,且这个公共串有单调性,即公共串越短越能满足条件,越长越不能满足条件。所以考虑二分答案。5.原创 2021-08-02 02:46:13 · 171 阅读 · 0 评论 -
[hdu多校] Kanade Loves Maze Designing
本题就是要求一棵树上两节点之前权值的个数。曾经做过求序列上两点间区间的权值个数问题, 用的是“±1法”即在遍历的过程中ans++或者ans–。int cnt[maxn],ans=0;for (int i=l; i<=r; i++){ cnt[a[i]]++; if (cnt[a[i]]==1) ans++;}这样的方法在[Luogu]P1638逛画展结合“尺取法”出现过。如今要用在树上,只不过我们不能用for循环遍历,而应该用dfs遍历。还有就是不能确定两点求,应该选定根节点求与原创 2021-07-30 01:21:28 · 145 阅读 · 0 评论 -
线段树
线段树的基本操作今天接触了线段树这个高端东西,花了半天才研究明白const int maxn = 1e5+5;int arr[maxn<<2]={0},change[maxn<<2]={0},lazy[maxn<<2]={0},update[maxn<<2]={0},sum[maxn<<2]={0};void pushup(int rt) //合并操作 { sum[rt]=sum[rt<<1]+sum[rt<&l原创 2021-01-25 18:14:19 · 101 阅读 · 0 评论