算法模板
Tz_rain
需要做的事情
解题 总结 巩固
解题三个步骤
量化 分析 实现
需要改变的三个问题
性格 心态 思考方式
不要再后悔
展开
-
LCA(最近公共祖先)
对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。现在给定一个根为1的树,求某两个点的最近公共祖先。原创 2016-10-09 16:13:33 · 243 阅读 · 0 评论 -
SRM 562 Div1 500 CheckerFreeness
/* 通过枚举一对黑点(l,r)。 我们可以计算出其他所有白点和他们的相对位置(用叉积表示) 我们把剩余的白点以和直线(l,r)的左右位置分成两部分 我们用pos表示在线段l -> r左侧的点,其相对于l,相对于r,分别是顺时针第pos[i].fr, pos[i].sc个点。 lim表示在l -> r右侧的点,与它,选中的l,r,能形成凸多边形的原创 2017-05-04 20:13:03 · 383 阅读 · 0 评论 -
二分图最大匹配专题
二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。二分图的一个等价定义是:不含有「含奇数条边的环」的图。图 1 是一个二分图。为了清晰,我们以后都把它画成图 2 的形式。匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。例如,图 3、图 4 中红色的边就是图 2 的匹配。例如图 3 中 1、4、5、7 为匹配点,转载 2017-03-04 08:35:26 · 284 阅读 · 0 评论 -
KMP
应用范围对于一个匹配串(S)和单个或多个母串(B)的问题流程先对匹配串造fail数组和AC自动机中的fail类似,即以失败的节点为右端点的复杂度约为O(n+m)O(n+m)void pre(){ fail[1]=0;fail[2]=1; for(int i=1;i<=m;i++){ int j=fail[i]; while(j&&S[i]!=S[j原创 2017-06-06 08:38:52 · 178 阅读 · 0 评论 -
专题:有关容斥原理和子集枚举的一些问题
容斥原理意义:有些问题中经常会出现这样一些烦人的限制条件如: 每个物品有一个额外的权如11011101,10011001, 我们最终答案的状态种一定要满足所取的物品,它们的权或后为11111111。此时如果这个值的位数很大我们之前学习过的知识对其就没有办法了。此时我们不妨分析一下最终的答案是怎么得到的。只要最终四个位上都有11就满足了对吧,不难发现如果我们把条件放宽一点:即最终得到的答案是1原创 2017-07-10 15:04:49 · 1081 阅读 · 0 评论 -
对弈(把九角距离转换为曼哈顿距离)
首先,可以知道,棋盘上A,B两点之间的距离(九向联通)等于max(|xA−xB|,|yA−yB|) max( \left| x_A-x_B \right| , \left| y_A-y_B \right| )。但是这个东西不好求和,需要对它做一个变形。设x′A=xA+yA2,y′A=xA−yA2x_A'= \frac {x_A+y_A}{2}, y_A'= \frac {x_A-y_A}{2}于原创 2017-07-12 18:35:03 · 253 阅读 · 0 评论 -
对拍
@echo off:p data.exe pro.exe std.exefc pro.txt std.txtif not errorlevel 1 goto ppausegoto p@echo off:p//自己命名 循环的名称 data.exe pro.exe std.exe fc pro.txt std.txt//比较函数if not原创 2017-07-16 09:44:57 · 226 阅读 · 0 评论 -
Tarjan算法详解
Tarjan算法的用途 1.求桥和割点 2.求点和边的双连通分量 3.求强连通 Targan算法的流程 利用dfs来遍历图来构建一种数型的结构 Tarjan算法的两个核心数组 dfn:我们用dfn数组记录 low:我们用low[i]表示一个节点的子树中可以到达最小的dfn (显然对于一个刚刚遍历到的点我们给他赋上一个新的dfn,low)<1>对于第一种用途 Tarjan算法原理原创 2017-03-16 19:49:19 · 823 阅读 · 0 评论 -
专题:关于搜索优化——A*和双向广搜
..原创 2017-07-07 15:44:16 · 1459 阅读 · 0 评论 -
专题:后缀数组——维护后缀排名的强大工具
什么是后缀数组我们有时会需要判断多个字符串后缀的的字典序大小,此时我们可以用后缀数组维护。原理我们利用倍增的思想,先比较长度为lenlen的字符串的字典序排名,之后在把他们合并起来。具体的合并操作和基数排序是类似的,由于基数排序的稳定性,我们先以第一关键字排序再以第二关键字排序会得到一个”稳定”的序列。所以我们可以把[l,len+l][l,len+l]的字典序排名为第一关键字把[len+l+原创 2017-07-08 09:35:51 · 264 阅读 · 0 评论 -
城市网络——可持久化栈
思路我们发现对于树上[l,r][l,r]的路径一定是包含在从根节点出发的某条链中的。而DFSDFS的过程中恰好便利了所有的这样的链于是我们可以用一个单调栈来维护有关链的答案。有了单调栈以后我们可以通过二分以o(logn)o(log_n)的复杂度来求解了。可是此时我们发现DFSDFS的过程中每次我们加入新的节点之后单调栈就发生了变化,在添加下一个节点的时候就不可用了。举一个简单的例子 可此原创 2017-07-08 20:30:59 · 667 阅读 · 0 评论 -
矩阵的的初步认识
矩阵的乘法运算 typedef vector<int> vitypedef vector<vi> matmat mul(mat A,mat B){ mat C(sz(A),vi(sz(B[0])); for(int i=0;i<sz(A);i++) for(int k=0;k<sz(B);k++) for(int j=0;j<sz(B[0原创 2017-03-27 22:32:10 · 251 阅读 · 0 评论 -
专题:强大的运算工具——矩阵
什么是矩阵对于 矩阵的的初步认识这里有一些讲解。一开始我对矩阵奇葩的运算方式感到奇怪,它有什么用。。。 DPDP问题的加速可以利用矩阵的结合律来实现。同时一些图论问题,利用矩阵有关图的联通和边权问题我们又有了一个新招了。(讲道理,要用到矩阵的题目似乎都是为它专门设计的。)同时还有其他的作用可以参考大牛的博客十个利用矩阵乘法解决的经典题目,codecode矩阵乘法在图联通中的原创 2017-07-10 09:45:38 · 977 阅读 · 0 评论 -
专题:迷之消维——CDQ分治
CDQ分治的用途我们可能一些问题,每个状态和操作有先后的关系(即ii的信息要从[1,i−1][1,i-1]转移或者调用)此时我们可以用CDQ分治以loglog的复杂度来降掉一个维度。 CDQ的基本流程对于[1,8]这一个需要从小到大操作的区间我们可以给它造一个树 之后我们按先序遍历依次地遍历并更新答案 void CDQ(int l,int r){ if(l==r)return;原创 2017-05-29 09:36:47 · 239 阅读 · 0 评论 -
Dsu on tree 神奇的暴力
什么是dsu这是一个很暴力很无脑的算法。 对于一棵树如果我们需要计算每个节点对应子树的信息。 由于每个父节点的信息来自每个子节点。我们来用以下的流程来合并信息。 为什么可以用dsu显然对于一个节点它只会被合并(lognlog_n)次所以复杂度可以为n∗(logn)n*(log_n) 例如我们要:统计子树内出现次数不少于k的元素个数。void dfs_pre(int x,int f){原创 2017-03-21 21:53:24 · 2770 阅读 · 2 评论 -
判断一个点与直线的相对位置
定义:平面上的三点P1(x1,y1),P2(x2,y2),P3(x3,y3) S(P1,P2,P3)= (x1-x3)* (y2-y3) - (y1-y3)*(x2-x3) 令矢量的起点为A,终点为B,判断的点为C, 如果S(A,B,C)为正数,则C在矢量AB的左侧; 如果S(A,B,C)为负数,则C在矢量AB的右侧; 如果S(A,B,C)为 0,则C在直线AB上。double s(原创 2017-05-03 19:34:56 · 3014 阅读 · 0 评论 -
AC自动机
使用场景在现实生活中有这样一个问题,如何把一篇文章中禁用的句子或单词(例如某些脏话)删去。如果把库(我们把禁用的句子或单词造成一个库)中的 每个串都和待配串(文章)进行判断子串的操作的话,效率也太低了。基本流程<1> build_trievoid build_tri(int x){//trie树:单词查找树 scanf("%s",str); int cur=0; for(原创 2017-05-22 22:38:14 · 191 阅读 · 0 评论 -
线段树的合并
原理和思路思路我们常常会遇到一些问题对于每一个点都有它的一些信息 然后我们需要查询一段区间 或者是树上一个点的子树信息此时我们便可以通过线段树的合并来解决这些问题原理我们通过把信息合并以后,利用合并后的线段树来实现lognlog_n的查询有时候我们也可以事先预处理好以方便查询 基本流程就像建主席树一样,对每一个点我们为它造一个树之后我们对不同的节点进行合并为了使合并可持久化我们原创 2017-05-11 19:25:48 · 335 阅读 · 0 评论 -
高精模板
十进制char tmp[M];struct bnt{ char num[M]; int len; bnt operator+(const bnt & t)const{ bnt c;c.len=max(len,t.len); for(int i=0;i<c.len;i++){ c.num[i]+=t.num[i]+num原创 2016-10-21 11:28:52 · 277 阅读 · 0 评论 -
二分图专题
1.bfs染色void dfs(int x,int c){ mark[x]=c; for(int i=0;i<edge[x].size();i++){ if(mark[edge[x][i]]==-1)dfs(edge[x][i],1-c); else if(mark[edge[x][i]]==c)f=false; }}int find(int原创 2016-10-14 19:18:46 · 268 阅读 · 0 评论 -
线段树的基础应用
(一)线段树的基本机构1.时间复杂度我们之所以使用线段树是因为它很多的操作都是o(log n)的 一个有n的叶子节点的树其深度约为log n 所以如果某个操作的在线段树复杂度为n将失去意义2.空间复杂度大约为叶子节点的4倍 (不知道为什么 )3.线段树的信息收集线段树父节点的信息可以利用up()从子节点提取的 同时线段树树上可以通过down()将父节点的信息给子节点void tree(int原创 2016-10-10 15:30:57 · 238 阅读 · 0 评论 -
树状数组专题
基本原理由于线段树上的任意一个区间(根除外)均可以用父区间减去另一个子区间得到 所以只存左区间也可以维护数的所以信息 如果想求[1,7]的和 由于7=>0111 所以sum[0111]=a[0111]+a[0110]+a[0100] 即:a[7]+a[6]+a[4];基本工作函数void add(LL *A,int i,int x){ while(i<=n)=A[i]+=x原创 2016-10-17 11:19:31 · 373 阅读 · 0 评论 -
树链剖分专题
基本定义 deep:深度 size:一个节点的子树的节点数 son:重儿子(size最大的) fa:节点的父亲 top:节点所在链的最高节点 基本思路 第一次dfs找到节点所有的基本信息; 第二次dfs沿着重儿子造成重链,以其他节点造新的重链; 于是树就被转化为链了。 然后再用其他数据结构优化 为了使所有的链连在一起我们可以给所有的点一个编号。 原理 由于一个点在被查询的过原创 2017-03-07 20:28:08 · 224 阅读 · 1 评论 -
正向表模板
正向表用于优化vector的速度。 注意正向表是反序查询的/*_________________________正向表_______________________________*/// !!!!!!!!!M=2*M;//NO.oneint tot,h[M];//标号struct node{ int to;//val int nx;//must have it point原创 2017-03-07 20:41:52 · 973 阅读 · 1 评论 -
莫队专题
莫队的使用范围莫队是一种暴力的区间查询的方法。复杂度为n*sqrt(n);以下面一题为例 装饰机房题目描述YCJS机房中挂上了好多画!机房后面的墙上整齐地挂上了一排n副画,画有许多种类,分别用1,2,3...表示。但是有许多画都重复了,XiaoC想要知道在一些区间中有多少副不同种类的画,以便他重新装饰这面墙。输入第一行包括原创 2017-03-07 20:46:53 · 221 阅读 · 0 评论 -
划分树
求区间第K大值 划分树#include<stdio.h> #include<algorithm> using namespace std; const int M=1e5+5; int T[20][M],S[M]; int toleft[20][M],n,m; void build(int l=1,int r=n,int p=1){ if(l==r)r原创 2017-03-22 21:28:35 · 216 阅读 · 0 评论 -
高斯消元
const double EPS =1e-8;typedef vector<double> vd;typedef vector<vd> mat;vd gauss(const mat &A,const vec& b){ int n=sz(A); mat B(n,vec(n+1)); for(int i=0;i<n;i++) for(int j=0;j<n;原创 2017-03-28 22:33:20 · 217 阅读 · 0 评论 -
主席树
主席树是什么主席树:是一种前缀树,通过一个地址root[i]−>root[i−1]root[i]->root[i-1]来实现的;建树 如上图所示,我们在插入元素的时候分别为每一个元素都给它建一个树void init(int &p,int l,int r){ p=++tot; T[p].v=0; if(l==r)return;原创 2017-03-23 21:28:00 · 423 阅读 · 0 评论 -
Splay专题
建树void build(int l,int r,int &id,int f){ if(l>r)return; int mid=(l+r)>>1; New(id,f,A[mid]); build(l,mid-1,ch[id][0],id); build(mid+1,r,ch[id][1],id); up(id); }void init(in原创 2017-04-02 20:46:24 · 301 阅读 · 0 评论 -
概率dp专题
概率dp例题 题意 一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcomponent,问他找到所有的bugs和subcomponents的期望次数。(s<=1000,n<=1000) 思路 我们发现dp的最终的状原创 2017-03-28 19:51:04 · 284 阅读 · 0 评论 -
bitset的一般用法
C++ BitsetsConstructorsbitset(); bitset( unsigned long val ); C++ Bitsets能以无参的形式创建,或者提供一个长无符号整数,它将被转化为二进制,然后插入到bitset中。当创建bitset时,模板中提供的数字决定bitset有多长。 例如,以下代码创建两个bitsets,然后显示它们: // 创建一个8位长的bitse原创 2017-04-12 20:55:58 · 705 阅读 · 0 评论 -
模拟退火算法
http://poj.org/problem?id=2420 题目大意: 给出平面上n个点,求到所有点距离和最短的点,输出该距离和。#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <time.h>struct pos{double x,y;}p[101];转载 2017-04-10 19:04:19 · 224 阅读 · 0 评论 -
[青蛙的约会 ]拓展欧几里得解同余方程
青蛙的约会题目描述两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为...原创 2019-06-09 15:19:53 · 163 阅读 · 0 评论