单调栈裸题 如果矩形高度从左到右是依次递增,那我们枚举每个矩形高度,宽度拉到最优,计算最大面积即可 当有某个矩形比前一个矩形要矮的时候,这块面积的高度就不能大于他本身,所以之前的所有高于他的矩形多出来的部分都没用了,不会再计算第二次. 因此我们只需要用单调栈维护矩形高度即可,当有高度较低的矩形进栈时,先将之前比他高的每个矩形弹出,宽度累加,更新答案.然后我们要进栈的矩形的宽度也要变成之前累加的宽度+1,因为要保留有用部分.. 有个小技巧:为了方便程序,在末尾加一个高度为0的矩形 #include…
Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11541    Accepted Submission(s): 3174 Problem Description A histogram is a polygon composed of a sequence of rect…
Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 12019    Accepted Submission(s): 3326 Problem Description A histogram is a polygon composed of a sequence of rec…
Problem Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of…
Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10873    Accepted Submission(s): 2969 Problem Description A histogram is a polygon composed of a sequence of rec…
                                     Largest Rectangle in a Histogram 这么经典的题硬是等今天碰到了原题现场懵逼两小时才会去补题...废话不多说: 题意:截取一个矩形使其面积最大,随你怎么截,反正面积要最大.输出最大面积,注意爆int. 思路:dp或单调队列.核心思路是从一个小矩形往两边扩散,分别找两边第一个小于这个矩形的位置,其中面积就是这个小矩形与区间长度的乘积,我们预处理出所有的小矩形的这两个端点值,然后扫一遍即可更新到最…
目录 题目 思路 \(Code\) 题目 Largest Rectangle in a Histogram 思路 单调栈. 不知道怎么描述所以用样例讲一下. 7 2 1 4 5 1 3 3 最大矩形的高度一定是给你的高度中的一个. 我们枚举最大高度. 很明显以某一高度为高的矩形的左边界是该高度左边第一个比它矮的. 右边界类似. 我们可以用单调栈去维护每一个高度左右第一个比他矮的位置即可 \(Code\) #include<iostream> #include<cstring> #i…
Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectang…
近期情绪太不稳定了.可能是由于在找实习这个过程碰壁了吧.第一次面试就跪了,可能是我面的是一个新公司,制度不完好,我感觉整个面试过程全然不沾编程,我面试的还是软件开发-后来我同学面试的时候.说是有一道数学题了.最后都已经签了,orz...其它同学都陆续签了,有签了知乎.有签了猎豹的,有签了阿里的,我还在想着打比赛,作为一个快大四的人.我还想着打比赛.甚至我连队友都快没了-可是我还想坚持!到如今,我基本没课了,每天都仅仅能是刷刷题,写写python,搞搞shell,我都不知道我在干嘛-!有没有大神给…
单调栈的介绍及一些基本性质 http://blog.csdn.net/liujian20150808/article/details/50752861 依次把矩形塞进单调栈,保持其单增,矩形中的元素是一个三元组,存储其位置,高度,以及以其为高度的情况下,大矩形的左边界最多扩展到哪里. 每次将新的元素塞进栈的时候,其左边界就是其左侧第一个小于它的矩形的位置+1. 然后,每个矩形出栈的时候,记录其右边界为当前往栈里面塞的矩形的位置-1,然后更新答案即可. 注意最后把所有的矩形出栈,更新答案. #in…
题意:http://acm.hdu.edu.cn/showproblem.php?pid=1506 如图,求最大的矩形面积 思路: 笛卡尔树:笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为key,一个为value.光看key的话,笛卡尔树是一棵二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大:光看value的话,笛卡尔树有点类似堆,根节点的value是最小(或者最大)的,每个节点的value都比它的子树要小(或者大). 笛卡尔树的构造算法:从右链插入,同时维护右链的递增或递减序列…
Die datenstruktur ist erataunlich! #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define R(a,b,c) for(register int a = (b); a <= (c); ++ a) #define nR(a,b,c) for(register in…
点分治 还是一道点分治,和前面那道题不同的是求所有距离小于等于k的点对. 如果只是等于k,我们可以把重心的每个子树分开处理,统计之后再合并,这样可以避免答案重复(也就是再同一个子树中出现路径之和为k的点) 但是对于这道题,如果我们还要这样求的话显然是会超时的,意外要枚举所有点的话有点勉强 ... 考虑一次把重心的子树全部遍历,统计到重心的距离,放进数组中,排序.然后我们可以用指针对撞的方法,用l,r两个指针分别从前后开始扫描. 容易发现,当指针再l的位置时,如果我们记录距离排好序的数组rd[l]…
树的直径 这题如果k=1很简单,就是在树的最长链上加个环,这样就最大化的减少重复的路程 但是k=2的时候需要考虑两个环的重叠部分,如果没有重叠部分,则和k=1的情况是一样的,但是假如有重叠部分,我们可以先把树直径找出来(最长链),然后把路径上的边权全部取反(1变-1),再找一次树的直径,如果第二次找的直径包含了取反的部分(即为重叠部分),这个重叠部分显然需要走两次. 可以推得答案为:2(n-1)-(L1-1)-(L2-1) 如果没有重叠部分,那么显然正确:假如有重叠部分,我们先减去了(L1-1)…
A* + dijkstra/spfa 第K短路的模板题,就是直接把最短路当成估价函数,保证估价函数的性质(从当前状态转移的估计值一定不大于实际值) 我们建反图从终点跑最短路,就能求出从各个点到终点的最短距离,这样就能满足估价函数的性质了 要注意一点,当起点和终点一样的时候第k短路就变成k+1短了,因为0也算一条... 话说回来为啥我用pair就MLE了呢.... #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace st…
单调队列优化dp dp真的是难..不看题解完全不知道状态转移方程QAQ 推出方程后发现是关于j,k独立的多项式,所以可以单调队列优化.. #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a, b) memset(a, b, sizeof a) using namespace std; typedef long long ll; inline int lowbit(int x){ return x & (-x);…
单调队列优化dp 我们把状态定位F[i][j]表示前i个工人涂了前j块木板的最大报酬(中间可以有不涂的木板). 第i个工人不涂的话有两种情况: 那么F[i - 1][j], F[i][j - 1]就成为了转移状态的候选. 那如果第i个工人要涂的话,我们可以假设我们是从k+1涂到j的,根据题意可以求出k的取值范围,然后状态转移的条件限制了j的取值范围. 我们考虑每j从小到大增加的过程,j对应的k的取值是一个上界不变下届变大的区间,是一个滑动窗口,那我们可以用单调队列来维护决策k的最优候选. #in…
01背包 我们对于这类选或者不选的模型应该先思考能否用01背包来解. 毫无疑问物体的价值可以看成最大的d+p值,那么体积呢?题目的另一个限制条件是d-p的和的绝对值最小,这启发我们把每个物体的d-p的值当作体积. 可以尝试设计状态f[i, j, k]表示从前i个物品中选j个,体积是k的最大价值. 同样的,我们可以用滚动数组的方法把第一维i去掉. 那么得到状态转移方程: f[j, k] = max(f[j - 1, k - d[i] - p[i]] + d[i] + p[i], f[j, k])…
dijkstra + 拓扑排序 这道题有负权边,但是卡了spfa,所以我们应该观察题目性质. 负权边一定是单向的,且不构成环,那么我们考虑先将正权边连上.然后dfs一次找到所有正权边构成的联通块,将他们看成点,那么负权边和这些点就构成了一张DAG. 对于DAG,我们可以拓扑排序,在排序的过程中,我们把入度为0的联通块里的所有点松弛一次,如果访问到联通块外的点,就让其入度减1,然后重复在拓扑排序中跑最短路的过程即可得到答案. 输出答案的时候注意一个坑,因为存在负权边,当有的点不能从起点达到的时候,…
hash + 二分答案 数据范围肯定不能暴力,所以考虑哈希. 把前缀和后缀都哈希过之后,扫描一边字符串,对每个字符串二分枚举回文串长度,注意要分奇数和偶数 #include <iostream> #include <cstdio> #define INF 0x3f3f3f3f #define full(a, b) memset(a, b, sizeof a) using namespace std; typedef long long ll; typedef unsigned lo…
拆点+网络流 拆点建图应该是很常见的套路了..一张无向图不联通,那么肯定有两个点不联通,但是我们不知道这两个点是什么. 所以我们枚举所有点,并把每个点拆成入点和出点,每次把枚举的两个点的入点作为s和t(这样方便,当然也可以把第一个点的出点当成s,第二个点的入点当成t,但其实我们把s和t的入点和出点之间的边容量设为INF之后就没有影响了) 每条原图的边连接着u的出点和v的入点,v的出点和u的入点,容量设为INF,保证不给割,其他点的入点和出点之间的容量当然是1.这样我们的割就一定会割在容量为1的边…
费用流 又是一道网络流的模型,对于这种费用与经过次数有关的边,我们经常把边拆成多条,比如这个题,第一次费用是x,第二次是0,我们就可以先把点拆成入点和出点,入点和出点又连两条边,第一条容量为1,费用为x:第二天容量为k-1,费用为0,意思很明确,第一次的流量可以得到费用,其他的流量都得不到费用. 原图坐标与坐标之间也连上容量为k,费用为0的边. 这样能保证网络中的最大流一定是k.(因为把源点当成(1,1)的入点,那么源点与他的出点只有k的容量). 我们在这个网络中跑最大费用最大流即可. #inc…
贪心 比较巧妙的贪心..先把所有机器和任务按时间是第一关键字,等级为第二关键字排序. 然后用机器去匹配每一个任务. 排序之后,在时间上满足当前任务的机器,必定也在时间上满足后面的机器,所以我们每次把时间满足当前任务的机器放进候选项中,再在候选项里选出当前任务等级的前驱即可 (时间和等级最大的任务先处理,且尽可能的不浪费机器) #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a, b) memset(a, b, sizeo…
二分 一道藏的很深的二分题... 题目保证只有一个点有奇数个防具,这个是突破口. 因为 奇数+偶数=偶数,我们假设某个点x,如果有奇数点的防具在x的左边,那么x的左边的防具总数一定是奇数,右边就是偶数 所以我们可以用这个来二分. 至于统计防具的公式,那就是小学学过的等差数列项数=(末项-首项)/公差+1.. #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a, b) memset(a, b, sizeof a) usin…
树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我们在树上的两个点路径上找到最大值a和次大值b,如果非树边(u,v)的权值大于a,那么用mst-a+w(u,v) 如果非树边(u, v)的权值等于a,那么用mst-b+w(u,v) 枚举完所有非树边之后,最小值就是严格次小生成树 对于每个点路径的最大值和次大值,我们可以和LCA一样,用树上倍增的方式…
LCA + 树上差分(边差分) 由题目意思知,所有主要边即为该无向图的一个生成树. 我们考虑点(u,v)若连上一条附加边,那么我们切断(u,v)之间的主要边之后,由于附加边的存在,(u,v)之间的路径形成了一个环, 所以我们还必须将这条附加边也切断. 因此我们可以看成(u,v)之间的路径上的所有边都被覆盖了一次. 我们可以统计出所有边被覆盖的次数,就可以自然的到答案: 若该边被覆盖了0次,那么切断主边之后随意切断一条附加边即可,答案总数 += 附加边的数量 若该边被覆盖了1次,那么切断主边之后必…
01边bfs 这题很容易想到的就是根据符号的情况建图,把每个点方格的对角线看成图的节点,有线相连就是边权就是0,没有就是1 然后跑最短路,但是最短路用的优先队列维护是有logn的代价的 这题还有一个更快的方法,就是双端队列..0边放队头,1边放队尾,然后虽然每个点会入队多次,但是我们只要取第一次出队(最短的情况)就行了 时间复杂度为O(r*c) #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typede…
模拟+dfs 这个题就三行,搜索的话我们从右向左,从上到下.. 如果是在1,2行我们就直接枚举0-n所有数,但是到了第三行,最直接的就是填上这一列上前两行的数的和modN,在此基础上判断该填的数有没有被使用 如果没有被使用,且这个地方没有被赋值,就可以把要填的数填上去,如果被填了切符合要求,就不需要填数了..注意每次填数都要维护下一列进位的值以及回溯 有一个非常重要的剪枝就是:对于一个竖式a+b=c,如果(a+b)modn != c 且 (a + b + 1)modn != c,那么这个竖式就是…
可持久化Trie 需要知道一个异或的特点,和前缀和差不多 a[p] xor a[p+1] xor....xor a[n] xor x = a[p-1] xor a[n] xor x 所以我们把a[1...n]的异或和预处理出来,用s[i]表示,用一个可持久化Trie维护 问题就转化成s[n] xor x = val,求一个序列与val异或的最大值 第i个Trie的root对应维护s[1..i],这样我们在查询值的时候为了保证在[...r-1]之类,只要查询r-1及之前的版本 为了保证在[l-1.…
还是数独.. 比上一个多了个分数矩阵,其实没什么差别,但是数据好像水了许多... #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; inline int lowbit(int x){ return x & (-x); } inline int read(){ int X = 0, w = 0; char ch = 0; while(!isdigit(ch)…