- 博客(98)
- 收藏
- 关注
原创 LRU算法 C++实现(HashMap+双向链表)
leetcode上测试代码的题目LRU(最近最少使用算法),是缺页置换解决方法中的一种。时间复杂度优秀O(1),空间复杂度不算哈希表本身的消耗的话还会多出维护双向链表左右指针的2N大小的空间消耗。具体实现方法就是在原有数据结构(一般是哈希表)的基础上套上一个双向链表。当操作(询问,修改,增加)某个链表中某个元素的时候把这个元素移动到链表头上。当缓存区满了的时候去掉链表尾上的那个元素即可。代码实现(HashSet和双向链表都是自实现的):class LRUCache {public: sta
2022-01-22 14:25:17
810
原创 Leetcode 第273场周赛题解
第一次打leetcode的比赛,打的virtual,简单说下每题的思路。反转两次的数字大意:判断一个数字翻转两次后是否还是原来的数字,翻转后要去掉前导零。只要末位不是零翻转两次肯定没变化,要特判一下0代码:class Solution {public: bool isSameAfterReversals(int num) { if(num == 0) return true; return num % 10; }};执行所有后缀指令大意:给
2021-12-29 13:19:13
385
原创 leetcode 297. 二叉树的序列化与反序列化
传送门题目要求序列化和反序列化一颗树,先抛开树结点的值,先解决如何确定一颗树的结构这个问题?第一时间想到的方法是用先中序或者是中后序的遍历结果来确定一棵树。再看看题目的限制,树的大小是1e4,结点值是1e3,最坏情况空间和时间复杂度是1e7级别的,勉强可行。再来思考如何确定每个节点的值这一问题,因为可能有重复的值,所以要正确储存一颗树的结构和值,需要对原树进行一点处理。具体方法如下:序列化用先序遍历的顺序结果对每一个节点进行重新赋值。在先序遍历的同时将节点上的原值存在一个字符串中。之后再进行中序遍历,
2021-12-25 14:43:41
425
原创 ubuntu opengauss使用教程
环境要求python3+推荐使用pyenv来管理我们的python版本,这样能避免很多不必要的麻烦使用教程:https://github.com/pyenv/pyenv跟着github的教程一步一步走应该就能搞定了。docker// 安装~$ sudo apt install docker.io// 检查~$ docker -v// 启动~$ sudo systemctl start docker// 开机启动~$ sudo systemctl enable docke
2021-10-09 23:30:23
1209
原创 Guess the K-th Zero (Hard version) (交互式,二分)
TP这场div3和另一场div2都有交互式的题目,以前很少接触CF上面的交互式题目,还是挺有意思的。在c++里,要得到交互式的答案只需要输出的时候注意用endl或者cout.flush()即可,得到的答案可以直接用cin存到变量里。easy version的题目很简单,直接二分位置即可。hard version在easy的基础上多增加了询问和改变值的操作,注意到题目只给了6n次的询问机会,如果和easy version一样粗暴的使用二分,时间复杂度可以接受,但是询问的次数不够用了。所以我们需要把询
2021-05-15 20:54:40
188
原创 Linux 使用动态优先权的进程调度算法的模拟 链表version 堆version
实验要求:1.对N个进程采用动态优先权算法的进程调度。2.每个用来表示进程的PCB包含一下字符段:(1) 进程标识数ID,(2) 进程优先数PRIORITY(3) 进程已占用CPU的时间CPUTIME(4) 进程还需要的CPU时间ALLTIME(5) 进程状态STATE3.优先数改变规则:进程在就绪队列中每呆一个时间片,优先数加1,进程每运行一个时间片优先度减3。4.设置调度前的初始状态。5.将每个时间片的进程情况显示出来。这个实验说是进程调度问题,其实就是算法比赛中的模拟题,先总结一
2021-04-15 21:30:36
250
原创 Linux 利用消息队列进行进程通信
除了pipe之外,Linux进程通信还可以用消息队列完成。主要用到的有以下几个函数:msgget(key_t key,int msgflg) 用于创建或找到一个消息队列,返回该队列的id,这个函数需要两个参数,key类似于rand函数中的种子,一般使用ftok函数生成。msgflg参数用于描述该消息队列的控制权限。ftok(char * filename,int id) 用于生成一个key值,在linux中利用文件的设备编号和节点的唯一性来生成唯一的key。msgctl(int msqid, int
2021-04-04 15:10:25
189
原创 Linux 关于fork函数和sleep函数以及通信管道的一些思考
在学进程通信的时候接触到了下面这段代码,里面的注释是我自行添加的。#include<stdio.h>#include <unistd.h>#include <string.h>#include <sys/wait.h>#include <sys/types.h>#include <stdlib.h>int main(){ int fd[2]={0,0}; // 0为读端,1为写端 if(pipe(fd)
2021-03-27 00:27:02
870
原创 ICPC打铜记
赛前准备: 前几天被师兄拉着打了ICPC的济南站,打这场前一周打了上海站的virtual,结果打铁了,在那之前对ICPC的题目走向和难度没有任何认知,平时做题的重心也不在思维题上.所以打完之后反思了一下,决定在这仅剩不多的一星期里多刷点CF和Atcoder.起码把铜牌题写熟一点.之后在热身赛前一两天打了一下ICPC南京的virtual,这次比较好,做出来了三题,另一个铜牌题主要死在了题意上,看不懂期望.之后就是热身赛和正式赛了.热身赛: 热身赛比较顺利,A题看了一眼就感觉是找n之前最大的条件数就是答案了,
2020-12-29 21:59:32
1257
原创 E. Weights Distributing(思维,单源最短路交集)
传送门做法应该不难想到:对a求一遍最短路,对b求一遍最短路,然后看a->b和b->c的交了多少条边,贪心的把交边赋值成为小权值即可。难点在于这个交集如何去求解,不妨换一种思路,去枚举这个交点x,那么路径的走向就是a->x->b->x->c.可以观察到b->x的路径走了两遍,所以只需要把b->x路径上的边赋最小的若干个权值即可。具体做法就是先对p数组排序求一遍前缀和,然后a,b,c各bfs求一遍最短路。枚举x每次统计p[dis[x][1]] + p[dis
2020-12-25 22:19:05
125
原创 Codeforces Round #547 (Div. 3) 题解
A. Game 23乘2和乘3的次数显然不会太多,暴力dfs即可。代码:#include <bits/stdc++.h>#define fir(i,a,b) for(int i = a;i <= b; ++ i)using namespace std; int n,m,ans;void dfs(int now,int cnt){ if(now > m) return; if(now == m){ ans = min(ans,cnt); return; }
2020-12-25 16:59:52
128
原创 Codeforces Round #690 (Div. 3) 题解
A. Favorite Sequence模拟题代码#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb push_back#define mem(a,x) memset(a,x,sizeof a)#define pii pair<int,int>#define fir(i,a,b) for(int i=a;i<=(int)b;++i)#define af
2020-12-18 22:14:50
219
1
原创 牛客小白月赛30 全题解
最近比赛状态有点迷,这场题目其实都挺简单的.压根没涉及到高级的算法和思维.A-黑白边最小生成树裸题.判断一下无解就好了.代码:#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb push_back#define mem(a,x) memset(a,x,sizeof a)#define pii pair<int,int>#define fir(i,a,b) f
2020-12-06 15:28:22
539
原创 F. Array Partition (思维+单调栈)
传送门题目大意:给一个数组,问能否把数组分为三段区间满足:max(1,x)=min(x+1,x+y)=max(x+y+1,n).某场Div3的最后一题.思维和编程难度都不算小.考虑枚举一下这个数是多少,那么这个数起码在数组里要出现三次以上.只有这种数才有机会成为答案.max和min有一个很明显的性质:当值域集合大小增大时,max会更大,min会更小.那么对于每一个数来说,两个max区间只要取最左边和最右边的两个数即可,中间的数可以暴力枚举.只要这中间的数产生的区间和其他两个区间有交集即可成为答案
2020-12-04 15:15:34
276
原创 [SCOI2012]喵星球上的点名(后缀数组+莫队+ST表)
传送门这题是真的秀.一眼看下去感觉AC自动机很可做,第一个问比较好处理,dfs序即可搞定,可第二问有点抽象,目前对树形结构的知识点不足以支持我解决这个问题.所以舍弃AC自动机,用SA做.SA做法: 做法比较套路,刚接触SA算法可能不太好想. 把所有字符串(询问串+模式串)都串成一个大字符串,中间用互不相同的字符隔开. 然后对这个串求SA和Height数组.在读入询问的时候,记录一下每个询问串的起点,求完SA和Height数组后求出每个询问串在SA数组中LCP(i,j) >= len的区间[L,R
2020-11-28 22:23:11
160
原创 数据结构二叉树实验报告
第一个实验是求一颗树的结点个数,叶子结点个数,某一个结点的深度,以及整颗树的宽度.先来考虑一下如何读入一颗树.其实递归的读入左右子树即可.参考代码:树的结构体:struct Tree{ char data; Tree * lson,* rson;};读入部分bool input(Tree *now){ // 这部分只是读入这颗树,不一定要这么写 cin >> now->data; if(now->data == '0') return
2020-11-22 17:52:33
4534
原创 AtCoder Beginner Contest 183 全题解
由于CF的比赛时间实在是有点晚,最近开启了AtCoder的比赛生涯.Beginner的题目有点类似CF里的Div3.甚至要更简单一点.主要是题目给的样例基本上能把BUG都找出来.A是语法题.B是数学题.要注意的是尽量控制精度到题目给定误差的范围那里.不然会WA太水就不给代码了C是简单dfs.注意一下回到1的时候要把耗时也给加上就行了.参考代码:int t[10][10];int K,vis[10],n,ans;void dfs(int pre,int k,int val){ if(
2020-11-22 16:26:36
331
原创 P4287 [SHOI2011]双倍回文(PAM(回文自动机/回文树),manacher)
传送门这题似乎用manacher可做而且很快,但用PAM做可能更好理解.看了题解都是用fail指针来写这题,但其实可以不用那么麻烦.考虑一下双倍回文的性质.1.首先肯定是一个回文字符串.2.从中间分开两边都是回文串.3.长度是4的倍数.暴力:第一个性质保证了它一定在PAM的一个节点上,我们可以最暴力的对每个节点判断是否是双倍回文.这种做法就不提了.正解:双倍回文串在PAM上的特点是它的转移字符形成的字符串一定是回文串.比如说abbaabba. 在PAM上它是这么形成的:a->b->
2020-11-20 15:31:08
187
原创 P3121 [USACO15FEB]Censoring G(AC自动机+STL)
传送门洛谷的标签和题解都说这题需要用栈,但其实用一个记忆数组pre+string类的earse函数就够了.只需要每次跑到可以删除的状态,直接删然后跑回pre[i-len]就可以了.代码#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb push_back#define mem(a,x) memset(a,x,sizeof a)#define pii pair<int,
2020-11-19 15:45:57
259
原创 P2414 [NOI2011]阿狸的打字机(AC自动机,dfs序,离线,优化建图)
传送门这是一道练习AC自动机的好题.先来考虑一下题目特殊的读入方式.如果把每个字符串存起来一个一个插入AC自动机的话这种做法最多只能过四个点.因为存储字符串的空间复杂度是O(|S|2)的.S的最大长度在1e5.这显然是不可接受的.优化一下建Trie树的过程.可以观察到这种生成字符串的方式会产生很多重复的结点.所以我们直接在读入的时候跳Trie树的指针就可以了,在接收到B的时候跳回p的父亲节点就可以了.接收到正常字符就正常跳指针.再来考虑一下怎么处理询问.先假定我们读入的字符串是正常一个一个读入的,那
2020-11-18 13:27:04
230
原创 洛谷 P3065 [USACO12DEC]First! G(trie树+拓扑排序)
传送门先建好trie树,然后考虑怎么搜索这个树来得到正确答案.如果一个字符串能够成为重新规划后字典序最小的那一个,那它在每一层上面都要大于其他节点.所以我们只需要一层一层的往下搜索,然后把其他节点看做一个点,建一条u->v的边,u是当前字符串,v是其他节点.最后判断建出来的图有无环即可(拓扑排序完成).还要注意的是如果这颗树里存在这个字符串的前缀串的话也是非法的.这种非法情况无法用拓扑序判断,可以外加一个trie树常见的ed数组来判断.用惯了namespace之后代码看起来感觉还是比较舒服的:
2020-11-13 20:27:31
290
原创 P4602 [CTSC2018]混合果汁(整体二分+主席树)
传送门多个询问且答案显然是具有单调性的,很自然的能想到整体二分.这题的难点可能是如何在二分的过程中快速处理数据.二分这个maxd的时候,需要对美味度在1~mid的果汁按价格排序,如果每段都排序的话复杂度会退化,这题不和其他整体二分的题目一样,不能直接把询问放到右区间的同时减掉cost.因为maxd增大了,可能会有更便宜的果汁供我们选择.观察到只需要知道1~前缀的排序序列,这个显然可以用主席树(或者说可持久化的权值线段树)来维护.具体来说就是把每个果汁的权值当作节点,维护num和sum两个变量,num表
2020-11-05 16:43:15
229
原创 CF1433 F - Zero Remainder Sum(分组背包,余数分组)
传送门按照题目的意思,我们可以把每一行看成一组,然后把每一行处理出来当做分组背包来做,但如果直接暴力去做的话值域太大,所以我们可以按照这题的特性,因为k很小,所以我们按照余数来区分这些值域,处理好每一行的复杂度是(35×70×70×35),之后的分组背包dp复杂度是(70×70×70),足以过这题.#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb push_back#defi
2020-10-24 15:22:11
308
1
原创 C Two Arrays(线性DP,前缀和)
传送门题目思路很好想,用dp[i][j][k]表示第i个数,a[i]放j,b[i]放k的方案数.暴力转移的话复杂度是O(m×n4),用前缀和可以优化到O(m×n2).dp[i][j][k] = sum{dp[i-1][1->j][k->n]}代码#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb push_back#define mem(a,x) memset
2020-10-18 13:51:15
199
原创 1285E Delete a Segment (扫描线)
传送门一眼看下来感觉就是线段树,但修了很久才修好.这题有一个很坑的点,不只有线段染色,还有单点染色,所以不能用i表示i-i+1有线段,不然的话单点染色无法操作.所以只能用i表示点.而维护线段的连通性可以在左右两端加两个标记,lc,rc.lc表示左端有线段连到左边,rc表示右端有线段连到右边.然后在修改的过程中修改这两个标记.#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb pu
2020-10-17 14:00:11
198
原创 洛谷P3863 序列(离线+分块)
传送门最直观的想法是维护N个元素每个时间的状态.这个做法显然不切实际,但似乎在线去做又没有什么很好的办法,所以只能考虑离线.离线做法:因为只有单点查询,所以我们可以按照每个修改和询问的位置排序.然后只维护每个时间点的状态.修改可以拆分成两个操作,在l位置上修改time-m的值,在r+1位置撤销这次修改.然后离线的一个一个处理询问就可以了.而询问可以转化成1-time-1有多少个数>=y-a[pos].这个可以用分块来处理.对每个块排序然后跨块的时候二分就可以了.#define LL long l
2020-10-02 13:28:47
217
原创 P3302 [SDOI2013]森林(主席树,启发式合并)
传送门写这题需要点亮的技能有:LCA(倍增orLCT求法),启发式合并,主席树.先讲暴力的算法,我们可以用并查集维护这个森林,当两个点连通的时候,我们暴力的去遍历其中一棵树,建立新的LCA和主席树两种结构,这个很好搞定.问题是,这样的时间复杂度和空间复杂度都不可承受,下面介绍启发式合并的思想优化这个算法.启发式合并这个东西,是一个很神奇的思想,因为这是一个森林,而且点集的规模是只增不减的,这类题目我们可以用并查集+启发式合并,优化暴力算法.考虑合并的时候把小的点集合并到大的点集里,那么这个合并复杂度会
2020-09-28 00:42:57
186
原创 线段树分裂与合并 学习笔记
线段树是很基本的一种数据结构,也是一种很强大的数据结构,它的衍生有权值线段树,可持久化线段树(主席树).还有现在要介绍的分裂合并版本的线段树.为了方便,下面的文章都用合并树来代替这一长串的称呼.这种线段树的一般套路都是维护权值,而不是维护序列.一般来说,合并树的基本操作就以下两种:add:void add(int &now,int l,int r,int p,int v){ if(!now) now = ++tot; tree[now].sum += v; if(l &
2020-09-27 01:10:16
274
原创 Sublime Text Snippet(代码片段)功能使用方法
Snippet是很多编辑器都有的功能,简要概括就是储存我们写过的代码,可以直接用几个简单的字符当做指令写出一大段常用的代码.首先,你得有个Sublime Text.点击上方的工具后点击里面的插件开发,在点击新建代码片段,就会得到如下的界面其中第一个红箭头中的一行是储存我们需要的代码片段,第二个红箭头是呼叫该片段的指令.使用的时候直接打出设置好的指令就ok了(要记得把前面的<!–删除掉).写好后ctrl+s保存到自己创建好的文件夹中就好了.使用样例:...
2020-09-20 20:26:08
1760
原创 P4309 [TJOI2013]最长上升子序列(平衡树,FHQ Treap实现)
传送门一道平衡树好题因为每次插入的数都是最大的数,所以我们只需要找到插入位置pos的前缀中的LIS,就可以得到此次插入的答案。再把这个答案和全局最大值比较就是此次操作的答案。如何维护一个前缀的LIS就是本题需要实现的操作。有的题解用了线段树+平衡树维护这个前缀LIS,但其实只使用一个平衡树就够了,具体做法:考虑按大小分裂的treap,节点中记录一个val,代表该位置结尾的LIS,以及记录一个mx代表该位置前缀的LIS。为了维护前缀的LIS,我尝试过几种错误的方式:乱搞一通维护的mx只包含了左子
2020-09-18 08:49:40
196
原创 洛谷 P2596 [ZJOI2006]书架 (平衡树,fhq treap详解)
传送门fhq treap对于区间的操作可谓是很简单很暴力,但是在没有完全理解fhq treap之前可能会对区间操作一脸懵.这篇博客希望能帮助到大家理解fhq treap的区间操作.我们要明确一个点,fhq treap维护平衡的方式就是split和merge操作,这两个操作保证和平衡树的性质.但这是按值分裂的fhq treap所采取的方式.而区间操作就显得更加暴力了,说是一颗平衡树,其实又不太像广义上面的平衡树.树的分裂不是靠值,而是靠大小(这就很强了).所谓的建树,只是把一个一个的结点拼接起来.先拼接的
2020-09-17 21:03:25
267
原创 HDU4261 Estimation(dp,对顶堆)
传送门一道dp水题.这32s的时限真是活久见.考虑用dp[i][j]表示前i个数分了j组能得到的minvalue.那么转移方程就可以列出来:dp[i][j] = min(dp[k][j-1] + value(k+1,j))意思是把k+1-i划分为新的一组.那么关键就在计算这个value函数.很显然,我们只要找到k+1-i的中位数作为b[k]就是最小的代价.这个过程可以用一个对顶堆预处理出来,找到之后还要计算代价.如果暴力的去算的话预处理的复杂度是O(n3)的,虽然有32s的时限也依然会超时.所以需要
2020-09-13 21:55:28
213
原创 [SCOI2010]股票交易(dp,单调队列)
传送门很有训练价值的一道单调队列dp题.状态表示很简单,dp[i][j]表示i天的时候有j股能赚到的最多的钱.朴素的转移方程(均以买入为例):dp[i][j] = max{dp[k][l] - (j-l)×ap[i], 1<=k<=i-w-1 && j-as[i]<=l<=j};这个方程复杂度是O(n4)的,可以过50%数据.优化到n3很简单,可以观察k的取值范围是1<=k<=i-w-1,只以i有关,且上界是不断扩大的,可以优化掉k那一维,用一
2020-09-13 15:17:43
137
原创 HDU2870 Largest Submatrix(单调栈,最大矩形面积)
传送门写dp的时候莫名其妙写到了这题,其实就是一个单调栈的模板题.观察后可以发现最后矩阵由’a’或者’b’或者’c’组成的时候能得到的最大子矩阵是最优的.所以枚举三种情况跑一遍单调栈维护一个递增的矩形就好了.代码#pragma GCC optimize(2)#define LL long long#define pq priority_queue#define ULL unsigned long long#define pb push_back#define mem(a,x) memset(
2020-09-12 20:37:46
127
原创 POJ 2288 Islands and Bridges(状压dp)
传送门一道难在初始化的题目.状态表示应该不难想到,状态i里某一位为1表示该点已经打通了,为0表示没打通.dp[i][k][l]表示在状态i的时候最后一个连通的点是k,倒数第二个连通的点是l能得到的最大值.转移方程也不难.枚举所有的1的位置j,然后根据题目给的价值转移,要注意的是j k l 三者都连通的时候需要计算第三个代价.状态表示和转移都很好解决,问题在于初始化.在只打通一个点和两个点这种情况下是不能这样转移的.所以对于这两种状态直接暴力的去做一遍.预处理出来.具体实现可以看代码中的count函数.
2020-09-12 14:58:35
117
原创 Codeforces Round #667 (Div. 3) A-D
在学校想打一场cf真是不容易.昨晚卡在E离散化的边界处理(也可能是思路错了)那里卡的很久,一直过不去就先睡觉去了.这场的题目偏易.大多都可暴力乱搞过去.A. Yet Another Two Integers Problem题目大意:给两个数,每次可以减去1-10,问最少多少次A==B.大概就是大数-10接近小数,如果%10的余数 大数大于小数的话,就要增加一次.#pragma GCC optimize(2)#define LL long long#define pq priority_queu
2020-09-05 15:32:36
120
原创 HDOJ5542 The Battle of Chibi(LIS拓展问题,树状数组优化转移方程)
传送门题意很简单:给定一个长度为N的序列A,求A有多少个长度为M的严格递增子序列。先考虑暴力的dp.设dp[i][j]表示的是以i结尾长度为j的LIS的数量.转移方程:dp[i][j] = sum{dp[k][j-1] 0 <= k < j && a[i] > a[k]}.代码:fir(i,1,n){ fir(j,1,min(i,m)){ fir(k,0,j-1){ if(a[i] > a[k]){
2020-08-21 13:42:24
144
原创 洛谷 P3959/NOIP2017 提高组 宝藏(状压dp,生成树)
传送门题目大意:给一个带权无向图,求生成树的最小代价.代价 = (起点深度dep[i]-1)*边权edge[i].n的范围只有12,很容易想到用状压来解决这道题.考虑怎么确定状态.代价只和深度和边权有关.我们可以把最大深度作为dp的阶段,各个点的打通情况作为附加状态.1表示已经打通,0表示尚未打通.再来考虑状态之间如何转移....
2020-08-19 15:30:23
242
1
原创 POJ2411 Mondriaan‘s Dream(状压dp,预处理)
传送门这种放置类的状压dp一般是按行划分阶段.状态之间的转移一般依据题目给的限制.例如这题提供了2种1×2的方块.横放的方块对下一行是没有影响的,只有竖放的方块才能影响到下一行.所以我们用1来表示竖放方块的上半部分,用0表示其他状态.再考虑不合法的状态,显然i-1和i行在第j列不能同时为1,可以直接用&来进行运算.还要注意的是如果第j列同时为0.说明至少有一行会横放方块.所以要有连续的偶数个0才可以放置.这一步用|来进行运算.到这里复杂度还是有点大,因为我们要对|运算的结果进行判断是否都是连续
2020-08-17 14:24:12
162
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人