动态规划DP的优化
写一写要讲什么免得忘记了。DP的优化。
大概围绕着"是什么","有什么用","怎么用"三个方面讲.
主要是《算法竞赛入门经典》里的题目讲解,但是有些过于简单的删去了,添加了一些不怎么简单的省选题目作为例子
这里的DP优化都是涉及到O(nk)到O(nk-1)方法比较巧妙也有用到数学里面的定理之类。
所以秉着由易到难的原则,安排内容如下:
专题1:动态规划基础知识和计数DP、数位DP(几大类DP的类型介绍)
专题2:DP的简单优化(稍微提两句mjy大佬的任务)
专题3:单调队列优化DP和斜率优化(这个比较难也比较重要) blog
专题4:四边形不等式优化DP
专题5:习题课
专题1:动态规划基础知识和计数DP、数位DP(几大类DP的类型介绍)
专题2:DP的简单优化(稍微提两句mjy大佬的任务)
专题3:单调队列优化DP和斜率优化(这个比较难也比较重要)
斜率优化DP blog、
将这个DP的优化方法之前我们必须看一个例子,优化的前提一直是暴力DP不错!
P3195 [HNOI2008]玩具装箱TOY
这个DP方程非常好想,F[i]从第1个到第i个物品放在箱子里的最小花费。
转移从第j个物品开始考虑在第j个物品放完之后的(i+1)到第j个物品放在一个容器中,每次决策一次那么得出方程式
为了方便起见我们这里的L++,然后用sum[x]表示C的前缀和那么DP方程就可以改写为:
然后我们发现对于确定的i,sum[i]+i的值是一定的,我们用s[x]表示sum[i]+i
进一步改写DP方程:
于是我们这个DP方程就显的优美了,不妨把暴力的代码打出来把:
# include<bits/stdc++.h>
# define int long long
# define SQR(x) ((x)*(x))
using namespace std;
const int MAXN=1e5+;
int s[MAXN],f[MAXN];
int n,L;
signed main()
{
scanf("%lld%lld",&n,&L); L++;
int t;
for (int i=;i<=n;i++)
scanf("%lld",&t),s[i]=s[i-]+t;
for (int i=;i<=n;i++) s[i]+=i;
memset(f,0x3f,sizeof(f)); f[]=;
for (int i=;i<=n;i++)
for (int j=;j<i;j++)
f[i]=min(f[i],f[j]+SQR(s[i]-s[j]-L));
printf("%lld\n",f[n]);
return ;
}
我们发现这样的算法时间完全承受不了,我们考虑优化!!!
优化用到的正是斜率优化。
为了O(1)转移我们必须寻求一种方法来找到最优的转移方案,
我们不妨把式子化简一下
对于当前最优的决策方案Fi,我们的每一个j都可以表示一个Fi的取值,这里取到最值,这和直线非常相似我们不妨把带有j的当做变量分离一下试试
b + k * x = y
我们发现这样一个神奇的式子,对于每一个j的取值都有一个在J(sj+L,fj+si2+(sj+L)2)与之对应,这个J就是坐标轴上离散的一个点,
就好比对于所有决策状态中的点J集合,一条直线(斜率K=2si已固定)经过这个J集合中至少一个点,使其截距b,尽可能小。
观察到题目中的c[i]都是正数意味着k=2*s[i]必然单调递增,我们承认的一个事实是在平面直角坐标系中一条直线k的值越大越陡,截距b越小
考虑怎样一个数据结构可以维护这样一个,单调递增k的特性呢?答案显然是单调队列,我们只要维护一个下凸包即可。
具体的解释是这样,考虑F[i]的斜率2*si如显然AB的斜率比F[i]的斜率小那么显然,A就是一个废弃的点(由于B的存在我宁可连B也不连A),我们就可以把它弹掉。
对于更新过的坐标集,第一个点的显然是最优的,由于满足下凸的性质,直线斜率不变,那么截距只能越来越大,这时候更新答案,更新完毕之后由于产生一个新的决策点J
我们需要对前面的点做一遍检查
对于新加进来的这个决策点new(就是当前的最优值),我们判断他是不是有资格作为后续DP状态的来源点,
如果new这个点和A这个点的斜率比BC的斜率还要小,那么BC这两个点将会被清除由于后续来的斜率线段一定会选择过new而不是B或者C
这也是基于上面的下凸包的性质。
提醒一下对于当前需要转移的i,我们可以不作记录的原因在于
对于每一个和i有关的常数我们都会在作差之中消除,我们可以不用理他(抵消!),这样程序就没有了i的干扰了!
Code:
# include<bits/stdc++.h>
# define int long long
# define SQR(x) ((x)*(x))
using namespace std;
const int MAXN=5e4+;
int sum[MAXN],F[MAXN],c[MAXN],s[MAXN],q[MAXN];
int n,L;
inline double X(int j){ return (double)s[j];}
inline double Y(int j){ return (double)F[j]+(s[j]+L)*(s[j]+L);}
//和i无关的每一个j点计算出他的横坐标和纵坐标
inline double R(int i,int j){return (Y(j)-Y(i))/(X(j)-X(i));}
//i下的两点斜率
# define Empty (head>=tail)
signed main()
{
scanf("%lld%lld",&n,&L); L++; sum[]=;
for (int i=;i<=n;i++)
scanf("%d",&c[i]),
sum[i]=sum[i-]+c[i],
s[i]=sum[i]+i;
int head=,tail=; q[]=;
//涉及到取两个元素的队列还是手打比较好
for (int i=;i<=n;i++) {
while (!Empty&&R(q[head],q[head+])<*s[i]) head++;
//不满足下凸的性质队头出
int j=q[head]; F[i]=F[j]+SQR(s[i]-s[j]-L);
//转移
while (!Empty&&R(q[tail-],q[tail])>R(q[tail],i)) tail--;
//不满足下凸性质的队尾出
q[++tail]=i;
//加入一个新的决策i
}
printf("%lld\n",F[n]);
return ;
}
//这个板子会在后面经常用到
这里还需要提高一下,我们其实不需要吧这个直线写出来就可以知道斜率,这样减少思维难度。
是这个方程,我们不妨考虑一个决策k在另一个决策j之前,但是k没有j优秀(对于更新外部循环变量i来说),
即
所以k这个决策无用抛弃。
可以化简为左边是si和sj或sk乘积形式除过去,就可以得到斜率
这个式子本质上是和上面是一样的,和R没有什么区别。
维护的话相似。
P2120 [ZJOI2007]仓库建设
考虑最简单的DP方程:
f[i]从山顶(1号)到第i号放完的最小代价
考虑f[i]从j转移过来。
设Wk表示如果将i这个地点作为建站处那么对于k<i的任意一个点,其代价
那么从1-j 已经处理完毕,考虑 j+1 到 i 这些物品的结构
转移方程:
对于需要转移的每一个x[i]不变,转移方程可以改写为
前缀和处理 -x[i]*p[i]和p[i]的前缀和分别为 g[i] 和 P[i]
这样复杂度降到了O(n^2)
帖下代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e6+;
int f[MAXN],x[MAXN],p[MAXN],P[MAXN],c[MAXN],g[MAXN];
int n;
signed main()
{
scanf("%lld",&n);
for (int i=;i<=n;i++)
scanf("%lld%lld%lld",&x[i],&p[i],&c[i]),
P[i]=P[i-]+p[i],g[i]=g[i-]-x[i]*p[i];
memset(f,0x3f,sizeof(f)); f[]=;
for (int i=;i<=n;i++)
for (int j=;j<i;j++)
f[i]=min(f[i],f[j]+x[i]*P[i]-x[i]*P[j]+g[i]-g[j]+c[i]);
printf("%lld\n",f[n]);
return ;
}
接下来将斜率优化的部分:
f[i]=f[j]+x[i]*P[i]-x[i]*P[j]+g[i]-g[j]+c[i]
f[i]+x[i]*P[j] = f[j] + x[i]*P[i] +g[i] - g[j] + c[i]
b + k * x = y
由于斜率单调递增,那么x[i]单调递增所以斜率单调递增,所以处理方法同上!
#include <bits/stdc++.h>
#define int long long
#define Empty (head>=tail)
using namespace std;
const int MAXN=1e6+;
int f[MAXN],x[MAXN],p[MAXN],P[MAXN],c[MAXN],g[MAXN],q[MAXN];
double X(int j) { return (double)P[j];}
double Y(int j) { return (double)f[j]-(double)g[j];}
double R(int i,int j){return (double)(Y(i)-Y(j))/(X(i)-X(j));}
int n;
signed main()
{
scanf("%lld",&n);
for (int i=;i<=n;i++)
scanf("%lld%lld%lld",&x[i],&p[i],&c[i]),
P[i]=P[i-]+p[i],g[i]=g[i-]-x[i]*p[i];
int head=,tail=; q[]=;
for (int i=;i<=n;i++) {
while (!Empty&&R(q[head],q[head+])<x[i]) head++;
int j=q[head]; f[i]=f[j]+x[i]*P[i]-x[i]*P[j]+g[i]-g[j]+c[i];
while (!Empty&&R(q[tail-],q[tail])>R(q[tail],i)) tail--;
q[++tail]=i;
}
printf("%lld\n",f[n]);
return ;
}
P3628 [APIO2010]特别行动队
先考虑暴力DP+前缀和优化!
设F[i]表示前i个士兵安排任务最大化战斗力,sum[x]表示x的前缀和数组
对于这个式子可以用前缀和表示,用F(x)=A*x*x+B*x+C代换可知
依然考虑斜率优化下,还是写成斜率的形式
依旧把有斜率的东西放到左边,右边保留一个解析式,就像这样:
b + k * x = y
这里是斜率k单调递减然后求fi最大值,其实只要向上面一样维护一个上凸包即可!
代码其实只要改两个符号就差不多了,理解就是取反然后按照斜率递增求Min一样就行。
code:
# include <bits/stdc++.h>
# define int long long
# define Empty (head>=tail)
using namespace std;
const int MAXN=2e6+;
int sum[MAXN],f[MAXN],q[MAXN*],A,B,C,n;
double X(int j){return sum[j];}
double Y(int j){return (double)f[j]+A*sum[j]*sum[j]-B*sum[j];}
double R(int i,int j){return (double)(Y(i)-Y(j))/(double)(X(i)-X(j));}
int Fun(int x) {return A*x*x+B*x+C;}
signed main()
{
scanf("%lld",&n);
scanf("%lld%lld%lld",&A,&B,&C);
int t;
for (int i=;i<=n;i++)
scanf("%lld",&t),sum[i]=sum[i-]+t;
int head=,tail=; q[]=;
for (int i=;i<=n;i++) {
while(!Empty&&(R(q[head+],q[head])>*A*sum[i])) head++;
int j=q[head]; f[i]=f[j]+Fun(sum[i]-sum[j]);
while (!Empty&&(R(q[tail],q[tail-])<R(q[tail],i))) tail--;
q[++tail]=i;
}
printf("%lld\n",f[n]);
return ;
}
到这里我们已经完成了斜率优化的入门题型这里给出几个练习,有助于能力提升:
专题4:四边形不等式优化DP
四边形不等式:相交小于等于包含
设w(x,y)是定义在Z上的二元函数,对于a<=b<=c<=d属于Z,都有w(a,d)+w(b,c)>=w(a,c)+w(b,d)
或者定义a<b,有w(a,b+1)+w(a+1,b)>=w(a,b)+w(a+1,b+1)
这两种定义是等价的!
证明:对于a<c,有w(a,c+1)+w(a+1,c)>=w(a,c)+w(a+1,c+1) (第2种定义)
对于a+1<=c,有w(a+1,c+1)+w(a+2,c)>=w(a+1,c)+w(a+2,c+1) (第2种定义)
两式相加,得:w(a+1,c+1)+w(a+2,c)+w(a,c+1)+w(a+1,c)>=w(a+1,c)+w(a+2,c+1) + w(a,c)+w(a+1,c+1)
消去相同项得:w(a+2,c)+w(a,c+1)>=w(a+2,c+1) + w(a,c)
同理对于任意的a<=b<=c有w(a,c+1)+w(b,c)>=w(a,c)+w(b,c+1)
同理对于任意的a<=b<=c<=d都有w(a,d)+w(b,c)>=w(a,c)+w(b,d)
证毕。
一维线性DP的四边形不等式优化:
对于形如 的一维线性DP方程,记录P[i]表示F[i]取到最小值的j,
若P[i]单调不减,则F具有决策单调性
定理:若val满足四边形不等式即val为凸(以后为了方便,满足四边形不等式的性质一律叫凸) 则F具有决策单调性
证明:令i在[1,N],j在[0,P[i]-1],i’在[i+1,N]
根据P[i]最优性,得F[P[i]]+val(P[i],i)<=F[j]+val(j,i)
由于val满足四边形不等式,有val(j,i)+val(P[i],i')<=val(j,i')+val(P[i],i)【相交小于等于包含】
两式相加,得:F[P[i]]+val(P[i],i)+val(j,i)+val(P[i],i')<=F[j]+val(j,i)+val(j,i')+val(P[i],i)
消去相同项,得:F[P[i]]+val(P[i],i')<=F[j]+val(j,i)
对于i'的最优决策P[i']在[P[i],i']不可能小于P[i],即P[i']>=P[i]
所以F满足决策单调性
在循环的任意时刻,数组中的情况一定是形如
由于决策单调则j1<j2<j3<j4<j5
求出F[i]后考虑i可能作为F[i'] (i'>i)的决策,那借用单调队列的思想考虑一个位置pos,之前的决策都比i好,之后的决策都比i差,
我们需要快速找到上述位置并把之后的所有元素改为i,把[pos,i]改为i,
假设我们的位子在j3(中间那个),那么处理后的数组就变为:
显然直接修改效率太低,我们在队列中用若干个三元组(j,l,r)表示数组的[l,r]最优决策都是j
另外队列中无需保留小于P[1~i-1]的部分,(由于F的决策单调性)
队列头部就是最优决策
算法:
- 检查队头(j0,l0,r0),若r0<=i-1,删除队头,否则l0=i
- 取出队头的决策j作为最优决策,状态转移求出F[i]
- 尝试插入新决策i:
- (1)取出队尾(jt,lt,rt)
- (2)对于F[lt]来说i是比jt更优的决策(由于决策单调对于lt来说i都优于此时的决策那么在队尾整个区间都差于此时的决策),pos=lt 删除队尾,goto(1)
- (3)对于F[rt]来说i不如jt更优 goto(5)
- (4)不满足(2)和(3)的,在[lt,rt]二分查找到pos,使之前的决策比i更优,之后的决策i更优(就说对于F[mid]来说,i决策比jt决策更优最小化mid),goto(5)
- (5)把(i,pos,N)插入队尾
# include <bits/stdc++.h>
# define int long long
# define ld long double
using namespace std;
const int MAXN=1e6+;
int N,P,L;
ld sum[MAXN],f[MAXN];
int last[MAXN],nxt[MAXN];
char s[MAXN][];
struct node{ int j,l,r;};
deque<node>q;
void Print_B()
{
puts("Too hard to arrange");
}
void Print_E()
{
for (int i=;i<=;i++) putchar();
putchar('\n');
}
void write(int x)
{
if (x<) { x=-x; putchar('-');}
if (x>) write(x/);
putchar(''+x%);
}
void writeln(int x)
{
write(x);putchar('\n');
}
inline int read()
{
int X=,w=; char c=;
while (!(c>=''&&(c<=''))) w|=c=='-',c=getchar();
while ((c>=''&&(c<=''))) X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
ld pow(ld x,int n)
{
ld ans=;
while (n) {
if (n&) ans=ans*x;
x=x*x;
n>>=;
}
return ans;
}
ld calc(int i,int j)
{
return (ld)f[j]+pow(abs(sum[i]-sum[j]+(i-j-)-L),P);
}
void Clear()
{
memset(f,,sizeof(f));
deque<node>tmp; swap(q,tmp);
memset(last,,sizeof(last));
memset(nxt,,sizeof(nxt));
sum[]=;
}
signed main()
{
int T; T=read();
while (T--) {
Clear();
N=read();L=read();P=read();
for (int i=;i<=N;i++) {
cin>>s[i];
int len=strlen(s[i]);
sum[i]=sum[i-]+(ld) strlen(s[i]);
}
q.push_back((node){,,N});
for (int i=;i<=N;i++) {
while (!q.empty()) {
if (q.front().r<i) q.pop_front();
else {
q.front().l=i; break;
}
} int j=q.front().j;
last[i]=j;
f[i]=calc(i,j);
int pos=-;
while (!q.empty()) {
int lt=q.back().l;
int rt=q.back().r;
int jt=q.back().j;
if (calc(lt,i)<=calc(lt,jt)) {
pos=lt; q.pop_back(); continue;
} else
if (calc(rt,jt)<=calc(rt,i)) break;
else {
int l=lt,r=rt,ans=;
while (l<r) {
int mid=(l+r)>>;
if (calc(mid,i)<=calc(mid,jt)) r=mid;
else l=mid+;
}
q.back().r=l-; pos=l; break;
}
}
if (pos!=-) q.push_back((node){i,pos,N});
}
if (f[N]>(1e18)*1ll) Print_B();
else {
printf("%lld\n",(int)(f[N]+0.5));
for (int i=N;i;i=last[i]) nxt[last[i]]=i;
int now=;
for (int i=;i<=N;i++) {
now=nxt[now];
int tmp=now;
for (int j=i;j<tmp;j++) printf("%s ",s[j]);
puts(s[tmp]);
i=tmp;
}
}
Print_E();
}
return ;
}
二维区间DP 四边形不等式定理:
(特别的要求F[i][i]=w[i][i]=0)
如果有下面条件成立:
- w为凸
- 对于任意的a<=b<-c<=d有w(a,d)>=w(b,c)
那么F也为凸。
由于我们定义二元函数的凸性是有两种定义方法,
我们就是要证明:对于任意 i< i+1<=j< j+1,满足f[i][j]+f[i+1][j+1]<=f[i][j+1]+f[i+1][j](交叉小于等于包含)
设f[i+1][j]取最小值的时候k=x,f[i][j+1]取最小值的时候k=y
f[i][j]=f[i][x]+f[x+1][j]+w(i,j)
f[i+1][j+1]=f[i+1][y]+f[y+1][j+1]+w(i+1,j+1)
所以左式取最值的时候,左式=f[i][x]+f[x+1][j]+w(i,j)+f[i+1][y]+f[y+1][j+1]+w(i+1,j+1)
由于w为凸,所以w(i,j)+w(i+1,j+1)<=w(i+1,j)+w(i,j+1)
f[i][x]+f[x+1][j]+w(i,j)+f[i+1][y]+f[y+1][j+1]+w(i+1,j+1)<=f[i][j+1]+f[i+1][j]
右式=f[i][y]+f[y+1][j+1]+w(i,j+1)+ f[i+1][x]+f[x+1][j]+w(i+1,j)
得:
f[i][x]+f[x+1][j]+w(i,j)+f[i+1][y]+f[y+1][j+1]+w(i+1,j+1)<=f[i][y]+f[y+1][j+1]+w(i,j+1)+ f[i+1][x]+f[x+1][j]+w(i+1,j)
展开得:
f[i][j]+f[i+1][j+1]<=f[i][j+1]+f[i+1][j]
证毕。
二维区间DP决策单调性定理:
如果 (特别的要求F[i][i]=w[i][i]=0)为凸
那么对于任意i<j都有P[i][j-1]<P[i][j]<P[i+1][j]
记p=P[i][j],对于任意的i<k<=p,由于F为凸那么f[i][p]+f[i+1][k]>=f[i][k]+f[i+1][p]
移项可得:f[i+1][k]-f[i+1][p]>=f[i][k]-f[i][p]
由于p最优,得f[i][k]+f[k+1][j]>=f[i][p]+f[p+1][j]
(f[i+1][k]+f[k+1][j]+w(i+1,j))-(f[i+1][p]+f[p+1][j]+w(i+1,j))
= f[i+1][k]-f[i+1][p]+f[k+1][j]-f[p+1][j]
>=f[i][k]-f[i][p]+f[k+1][j]-f[p+1][j]
= f[i][k]+f[k+1][j]-(f[i][p]+f[p+1][j])>=0
所以对于f[i+1][j],p比任何k<=p优所以P[i+1][j]>=P[i][j]
同理可知P[i][j-1]<=P[i][j]
四边形不等式优化定理总结
1.四边形不等式的定义:相交小于包含
两种等价定义:
对于a<=b<=c<=d属于Z,都有w(a,d)+w(b,c)>=w(a,c)+w(b,d)
对于a,b属于Z 若 a<b,有w(a,b+1)+w(a+1,b)>=w(a,b)+w(a+1,b+1)
2.一维线性DP决策单调定理
对于形如f[i]=min_{0<=j<i}{F[j]+w(j,i)}若w为凸那么F决策单调递增
3.二维区间DP决策单调性定理
对于形如F[i][j]=min_{i<=k<=j}{f[i][k]+f[k+1][j]+w(i,j)}
(特别的要求F[i][i]=w(i,i)=0) 若w为凸则F为凸,
对于F理应满足决策P[i][j-1]<P[i][j]<P[i+1][j]
P[l][r]表示当[l,r]分为[l,k]和[k+1,r]两部分时F[l][r]最大
利用第二种等价定义,证明函数w(x,y)的凸性事实上只要
证明对于任意j<i,w(j,i+1)+w(j+1,i)>=w(j,i)+w(j+1,i+1)
只需证明:w(j+1,i)-w(j+1,i+1)>=w(j,i)-w(j,i+1)
代入换元函数单调性可知w(x,y)的凸性
更方便的方案:打表暴力DP验证决策单调!
石子合并弱化版本 https://www.luogu.org/problemnew/show/U58387
石子合并强化版本 GarsiaWachs算法(这里放过了GW的暴力O(n^2)那是因为数据随机)
专题5:习题课
动态规划DP的优化的更多相关文章
- DP的优化总结
一.预备知识 \(tD/eD\) 问题:状态 t 维,决策 e 维.时间复杂度\(O(n^{e+t})\). 四边形不等式: 称代价函数 w 满足凸四边形不等式,当:\(w(a,c)+w(b,d)\l ...
- 【BZOJ1150】数据备份(动态规划,凸优化)
[BZOJ1150]数据备份(动态规划,凸优化) 题面 BZOJ 洛谷 题解 在不考虑\(K\)的情况下很容易\(dp\) 如果把\(K\)考虑进状态显然是\(O(n^2)\)级别. 所以凸优化一下即 ...
- 【BZOJ5311/CF321E】贞鱼/Ciel and Gondolas(动态规划,凸优化,决策单调性)
[BZOJ5311/CF321E]贞鱼/Ciel and Gondolas(动态规划,凸优化,决策单调性) 题面 BZOJ CF 洛谷 辣鸡BZOJ卡常数!!!!!! 辣鸡BZOJ卡常数!!!!!! ...
- 【BZOJ5252】林克卡特树(动态规划,凸优化)
[BZOJ5252]林克卡特树(动态规划,凸优化) 题面 BZOJ(交不了) 洛谷 题解 这个东西显然是随着断开的越来越多,收益增长速度渐渐放慢. 所以可以凸优化. 考虑一个和\(k\)相关的\(dp ...
- 【CF739E】Gosha is hunting(动态规划,凸优化)
[CF739E]Gosha is hunting(动态规划,凸优化) 题面 洛谷 CF 题解 一个\(O(n^3)\)的\(dp\)很容易写出来. 我们设\(f[i][a][b]\)表示前\(i\)个 ...
- 【BZOJ3437】小P的牧场(动态规划,斜率优化)
[BZOJ3437]小P的牧场(动态规划,斜率优化) 题面 BZOJ 题解 考虑暴力\(dp\),设\(f[i]\)表示强制在\(i\)处建立控制站的并控制\([1..i]\)的最小代价. 很显然,枚 ...
- 【BZOJ4654】【NOI2016】国王饮水记(动态规划,斜率优化)
[BZOJ4654][NOI2016]国王饮水记(动态规划,斜率优化) 题面 BZOJ 洛谷 题解 首先肯定是找性质. 明确一点,比\(h_1\)小的没有任何意义. 所以我们按照\(h\)排序,那么\ ...
- 【BZOJ】1096: [ZJOI2007]仓库建设(dp+斜率优化)
http://www.lydsy.com/JudgeOnline/problem.php?id=1096 首先得到dp方程(我竟然自己都每推出了QAQ)$$d[i]=min\{d[j]+cost(j+ ...
- 【Wannafly挑战赛29F】最后之作(Trie树,动态规划,斜率优化)
[Wannafly挑战赛29F]最后之作(Trie树,动态规划,斜率优化) 题面 牛客 题解 首先考虑怎么计算\([l,r]\)这个子串的不同的串的个数. 如果\(l=1\),我们构建\(Trie\) ...
随机推荐
- Linux 内核开发 - 内核定时器
时间差的度量 系统的定时器硬件以固定的频率产生时钟中断,产生始终中断的间隔以HZ 常量来决定,通常在50~1200之间,x86默认是1000.HZ能够依据不同的内核来配置. Linux 採用jiffi ...
- 一文让您全面了解清楚HBase数据库的所有知识点,值得收藏!
一.HBase基本概念:列式数据库 在Hadoop生态体系结构中,HBase位于HDFS(Hadoop分布式文件系统)的上一层,不依赖于MapReduce,那么如果没有HBase这种Nosql数据库会 ...
- 2.1《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——重定向文件和添加文件
回忆第一章节的内容,我们用echo命令输出莎士比亚的第一首十四行诗的第一行(Listing 6): $ echo "From fairest creatures we desire incr ...
- 64位RHEL5系统上运行yum出现"This system is not registered with RHN”的解决方法
在红帽EL5上运行yum,提示“This system is not registered with RHN”,意思是没有在官网上注册,不能下载RH的软件包,替代方案是采用centos源. 1.卸载r ...
- 20155330 《网络攻防》 Exp3 免杀原理与实践
20155330 <网络攻防> Exp3 免杀原理与实践 基础问题回答 杀软是如何检测出恶意代码的? 基于特征码.先对流行代码特征的提取,然后进行程序的比对,如果也检测到相应的特征码的程序 ...
- 如何取得Oracle并行执行的trace
如何取得Oracle并行执行的trace: ALTER SESSION SET tracefile_identifier='10046_PROD';ALTER SESSION SET max_dump ...
- 洛咕 P3756 [CQOI2017]老C的方块
四染色,贼好想 一个弃疗图形刚好对应一个红-绿-黄-粉色路线(不要吐槽颜色) 就是裸的最小割,建图傻逼懒得写了 #include<bits/stdc++.h> #define il inl ...
- centos 7 git的管理和使用
一.linux 安装git (服务端) 1.首先创建用户账号 useradd zlx passwd zlx .... 2.创建目录git仓库 mkdir zlx_git.git 3.赋权限 chown ...
- GitHub 新手教程 一,GitHub 注册
1,注册地址: https://github.com/ 2,输入账号.邮箱.密码: 3,选择 Free 免费账号: 4,选择一些基本信息(翻译后中文见下面的图): 翻译如下: 5,打开你注册用的邮箱, ...
- cocos2dx渲染架构
2dx的时代UI树便利和渲染是没有分开的,遍历UI树的时候就渲染.3dx版本为了分离了ui树的遍历和渲染,先遍历生成渲染命令发到渲染队列,之后遍历渲染命令队列开始渲染.这样做的好处是渲染命令可以重用, ...