T1:给出一棵 $n$ 个节点的无根树,其中 $m$ 个节点是特殊节点,求对于任意 $i ∈ [0, m]$,包含 $i$ 个特殊节点的联通块个数$\mod 998244353$。 $1<=n,m<=1000$

输入格式

第一行包含两个正整数 $n,m$,表示树节点个数及特殊节点个数。
第二行包含 $m$ 个互不相同的正整数,表示所有特殊节点的编号。
接下来 $n$ 行,每行包含两个正整数 $u,v$,表示一条树边。

输出格式

输出包含 $m+1$ 个用空格隔开的整数,以此表示 $i=0,1,2,...,m$ 时,包含 $i$ 个特殊节点的联通块个数对 $998244353$ 取模的值。

树上连通块计数题,首先想到树形DP。

$f(i,j)$ 表示以点$i$为根的子树中,取$j$个关键点且必选根节点$i$的连通块的方案数。

那么可以发现,当考虑以$i$为根的子树的时候,我们只考虑不同子树之间合并的连通块,因为同一子树之间的连通块可以根据此原则,在子树内完成所有统计。

那具体怎么转移?又回到了子树乘法原理问题了……(不如说是树上背包)

$f(i,j) = \sum_{son_i} f(son_i,k) * f(i,j-k) | j<=size(i), k<=j$ //size(i)表示以i为根的子树中的特殊节点数量

这转移一看就知道怎么回事了

在这之前先特判一下根节点$i$是不是特殊节点,如果是的话就把$f(i,1)$初始化为1,否则把$f(i,0)$初始化为1。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<vector>
  5. #define MAXN 131072
  6. #define MOD 998244353
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x=; bool f=; char c=getchar();
  11. for(;!isdigit(c);c=getchar()) if(c=='-') f=;
  12. for(; isdigit(c);c=getchar()) x=(x<<)+(x<<)+(c^'');
  13. if(f) return x;
  14. return -x;
  15. }
  16. int first[],nxt[],targ[],cnte=;
  17. bool special[];
  18. int ans[];
  19. int dp[][],cntd[];
  20. int poly[];
  21. void AddEdge(int u,int v)
  22. {
  23. targ[cnte]=v, nxt[cnte]=first[u], first[u]=cnte++, swap(u,v);
  24. targ[cnte]=v, nxt[cnte]=first[u], first[u]=cnte++;
  25. }
  26. void DP(int x,int Fa)
  27. {
  28. if(special[x]) dp[x][]=, cntd[x]=;
  29. else dp[x][]=, cntd[x]=;
  30. for(int i=first[x];i;i=nxt[i])
  31. {
  32. if(targ[i]==Fa) continue;
  33. int y=targ[i];
  34. DP(y,x);
  35. for(int i=;i<cntd[x]+cntd[y]-;i++) poly[i]=;
  36. for(int i=;i<cntd[x];i++)
  37. for(int j=;j<cntd[y];j++)
  38. (poly[i+j] += (long long)dp[x][i]*dp[y][j]%MOD) %= MOD;
  39. cntd[x] += cntd[y]-;
  40. for(int i=;i<cntd[x];i++) dp[x][i]=poly[i];
  41. }
  42. for(int i=;i<cntd[x];i++) (ans[i]+=dp[x][i])%=MOD;
  43. (++dp[x][])%=MOD; //一个点都不选的情况也要算上(一开始只特判了选非特殊节点的根节点)
  44. }
  45. int main()
  46. {
  47. freopen("tree.in","r",stdin);
  48. freopen("tree.out","w",stdout);
  49. int n=read(),m=read();
  50. for(int i=;i<m;i++) special[read()]=;
  51. for(int i=;i<n;i++) AddEdge(read(),read());
  52. DP(,);
  53. for(int i=;i<=m;i++) printf("%d%c",ans[i],i==m?'\n':' ');
  54. return ;
  55. }

时间复杂度根据均摊原则可知近似$O(nm)$

2018.10.1 update:这里证明了一下复杂度

T2:有 $n$ 个机器人和 $m$ 个配件,每个机器人需要若干个的配件。每个机器人对每个配件都有一定适配度,但都可互相搭配。现在请你求出,给每个机器人分配其所需数量的配件,所有机器人对其分配到的配件的适配度之和最大是多少?

输入格式

第一行包含两个正整数 $n,m$,依次表示机器人和配件个数。
第二行包含 $n$ 个正整数 $a_i$,依次表示从 $1$ 到 $n$ 号机器人所需配件数,保证 所需配件总数 $\leq m$。
接下来是一个 $n$ 行 $m$ 列的正整数矩阵 $C$,其中第 $i$ 行第 $j$ 列的数值表示,$i$ 号机器人对 $j$ 号配件的适配度。

输出格式

输出一个整数,表示答案。

$1<=n<=100, 1<=m<=200$

适配度最大值$S \leq 10^7$

不穿衣服的费用流裸题。

如此建图,从源点S到$i$号机器人连上流量为$a_i$、费用为$0$的边,从$i$号机器人到$j$号配件连上流量为$1$、费用为$C(i,j)$的边,从$i$号配件到汇点T连上流量为$1$,费用为$0$的边。这么建刚好限定了每个机器人选择配件的数量、每个配件只能被选一次,那么最大费用就是答案(注意我们平常写的是最小费用最大流!)

注意不要写EK,会被卡时成40分。

  1. #include<queue>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<iostream>
  6. #include<algorithm>
  7. #define inf 0x7f7f7f7f
  8. #define maxn 201
  9. #define maxm 401
  10. #define S n+m+1
  11. #define T n+m+2
  12. using namespace std;
  13. inline int read(){
  14. int x=,f=; char c=getchar();
  15. for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
  16. for(;isdigit(c);c=getchar()) x=(x<<)+(x<<)+c-'';
  17. return x*f;
  18. }
  19. class Dinic_Enhancer
  20. {
  21. private:
  22. struct edge{
  23. int v,w,x,next; //w表示流量,x表示费用
  24. }e[maxm<<];
  25. int cnt,head[maxn];
  26. int depth[maxn],cur[maxn];//cur就是记录当前点u循环到了哪一条边(弧优化)
  27. int dis[maxn],fa[maxn],faedge[maxn];
  28. bool inq[maxn];
  29. public:
  30. int n,m;
  31. void init()
  32. {
  33. cnt=;
  34. memset(head,-,sizeof(head));
  35.  
  36. n=read(),m=read();
  37. for(int i=;i<=n;i++){
  38. add_edge(S,i,read(),);
  39. }
  40. for(int i=;i<=n;i++)
  41. for(int j=;j<=m;j++) add_edge(i,n+j,,read());
  42.  
  43. for(int i=n+;i<=n+m;i++) add_edge(i,T,,);
  44. }
  45. void add(int u,int v,int w,int x)
  46. {
  47. e[cnt].v=v;
  48. e[cnt].w=w;
  49. e[cnt].x=x;
  50. e[cnt].next=head[u];
  51. head[u]=cnt++;
  52. }
  53. void add_edge(int u,int v,int w,int x)
  54. {
  55. add(u,v,w,x);
  56. add(v,u,,-x);
  57. }
  58. bool spfa()
  59. {
  60. queue<int> Q;
  61. memset(depth,,sizeof(depth));
  62. fill(dis+,dis+T+,-inf);
  63. memset(inq,,sizeof inq);
  64. depth[S]=;
  65. dis[S]=;
  66. Q.push(S);
  67. int i,u;
  68. while(!Q.empty())
  69. {
  70. u=Q.front(); Q.pop();
  71. inq[u]=;
  72. for(i=head[u];i!=-;i=e[i].next)
  73. if(dis[e[i].v]<dis[u]+e[i].x && e[i].w>)
  74. {
  75. dis[e[i].v]=dis[u]+e[i].x;
  76. depth[e[i].v]=depth[u]+;
  77. fa[e[i].v]=u, faedge[e[i].v]=i;
  78. if(!inq[e[i].v]){
  79. inq[e[i].v]=;
  80. Q.push(e[i].v);
  81. }
  82. }
  83. }
  84. if(dis[T]==-inf) return ;
  85. return ;
  86. }
  87. int dinic()
  88. {
  89. int ans=,i,flow;
  90. while(spfa())
  91. {
  92. int u=T,flow=inf;
  93. while(u!=S) flow=min(flow,e[faedge[u]].w), u=fa[u];
  94. u=T;
  95. while(u!=S) e[faedge[u]].w-=flow, e[faedge[u]^].w+=flow, u=fa[u];
  96. ans+=dis[T];
  97. }
  98. return ans;
  99. }
  100. }de;
  101.  
  102. int main(){
  103. de.init();
  104. printf("%d\n",de.dinic());
  105. return ;
  106. }
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<queue>
  5. #define MAXN 606
  6. #define MAXM 40040
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x=,t=,c;
  11. while(!isdigit(c=getchar()))if(c=='-')t=-;
  12. while(isdigit(c))x=x*+c-'',c=getchar();
  13. return x*t;
  14. }
  15. struct ZKW
  16. {
  17. int first[MAXN],targ[MAXM<<],nxt[MAXM<<],flow[MAXM<<],cost[MAXM<<],cnte=;
  18. int dist[MAXN],s,t,inf,ans=;
  19. bool inq[MAXN],vis[MAXN];
  20. void AddEdge(int u,int v,int l,int c)
  21. {
  22. targ[cnte]=v;flow[cnte]=l;cost[cnte]=c;nxt[cnte]=first[u];first[u]=cnte++;swap(u,v);
  23. targ[cnte]=v;flow[cnte]=;cost[cnte]=-c;nxt[cnte]=first[u];first[u]=cnte++;
  24. }
  25. bool SPFA()
  26. {
  27. memset(dist,,sizeof dist);
  28. memset(&inf,,sizeof(int));
  29. memset(inq,,sizeof inq);
  30. queue<int> Q;
  31. dist[t]=;
  32. inq[t]=;
  33. Q.push(t);
  34. while(!Q.empty())
  35. {
  36. int x=Q.front();Q.pop();inq[x]=;
  37. for(int i=first[x];i;i=nxt[i])
  38. {
  39. if(flow[i^]&&dist[targ[i]]>dist[x]-cost[i])
  40. {
  41. dist[targ[i]]=dist[x]-cost[i];
  42. if(!inq[targ[i]])
  43. {
  44. Q.push(targ[i]);
  45. inq[targ[i]]=;
  46. }
  47. }
  48. }
  49. }
  50. return dist[s]!=inf;
  51. }
  52. int DFS(int x,int maxflow)
  53. {
  54. if(x==t||!maxflow){ans+=dist[s]*maxflow;return maxflow;}
  55. if(vis[x])return ;
  56. vis[x]=;
  57. int ret=,f;
  58. for(int i=first[x];i&&maxflow;i=nxt[i])
  59. {
  60. if(dist[targ[i]]==dist[x]-cost[i])
  61. {
  62. if(f=DFS(targ[i],min(maxflow,flow[i])))
  63. {
  64. ret+=f;
  65. flow[i]-=f;
  66. flow[i^]+=f;
  67. maxflow-=f;
  68. }
  69. }
  70. }
  71. vis[x]=;
  72. return ret;
  73. }
  74. int solve(int source,int tank)
  75. {
  76. s=source;t=tank;int Flow=;
  77. while(SPFA())
  78. {
  79. Flow+=DFS(s,);
  80. }
  81. return Flow;
  82. }
  83. }zkw;
  84. int n,m;
  85. int main()
  86. {
  87. freopen("robot.in","r",stdin);
  88. freopen("robot.out","w",stdout);
  89. n=read();m=read();
  90. for(int i=;i<=n;i++)zkw.AddEdge(i+,,read(),);
  91. for(int i=;i<=n;i++)
  92. for(int j=;j<=m;j++)
  93. zkw.AddEdge(n++j,i+,,-read());
  94. for(int j=;j<=m;j++)
  95. zkw.AddEdge(,n++j,,);
  96. zkw.solve(,);
  97. printf("%d",-zkw.ans);
  98. return ;
  99. }

T3:有一维空间内 $n$ 个点,编号从 $1$ 到 $n$,编号为 $i$ 的点坐标为 $x_i$。现在,请选出编号连续的一些点,使得被选出的所有点到某一点的距离和的最小值不超过一正整数 $m$,问最多能选出多少点?

输入格式

第一行,包含两个正整数 $n,m$,依次表示点数和距离和限制。
第二行,包含 $n$ 个正整数 $x_i$,依次表示每个点的坐标。
输出格式

输出共一行,表示最多选取点数。

$1<=n<=10^5, 1<=m<=10^9, 1<=x_i<=10^6$

难度堪比提高组D2T3

第一眼看到这题,不会,于是想想暴力做法。

首先我们得知道这样一个幼儿园知识:n个数中,与这n个数的差的绝对值(在空间意义里就是距离)之和最小的数 是这n个数的中位数。

为什么?简单证明:

把这n个数从小到大排序。假设我们先认为与这n个数的差的绝对值(在空间意义里就是距离)之和(下面都称之为答案)是最小的数(第一个数),我们把答案改为第二个数,则从第1个数到第2个数的距离会增加$dis(1,2)$,第2~n个数到第2个数的距离都会减少$dis(1,2)$,那么很明显距离减少的比增加的多,距离总和也会减少。把答案从第二个数改为第三个数,再改为第四个数……一直改到中位数为止,距离减少的都比增加的多(距离减少的占一半以上),所以距离总和不断减少;而从中位数改到比中位数大的下一位时,距离增加的数就超过一半了,而距离减少的数随之少于一半,且之后距离增加的数会越来越多,这时距离总和就会不断增加。

总结一下,就是 总距离随数的排名的变化 的图像是单峰下凸的,且排名在最中间(中位数)时所有数到它的总距离最小。大家可以手动写个数列验证一下。

下面回到正题:

用两重循环枚举所有选点区间(按编号顺序),搜一遍区间里的点找出中间点(可以理解为n个坐标的中位数)并暴力求解所有被选点到它的总距离就可以了。

这样的复杂度是$O(n^3)$,可以过40%的数据。

我们很快发现最外层的两重循环枚举区间可以优化。这样想:一个选点区间的所有数到该区间中位数的距离总和不超过$m$的话,那更短的区间到其中位数的距离总和一定也能不超过$m$(至少把满足条件的选点区间中去掉头或尾一个点的情况就可以,总距离只会减少那个点到中位数的距离,不会增加,因此依然可以不超过$m$)。因此区间答案随区间长度单调递减,把其中一重枚举区间长度的循环改为二分即可。

这样的复杂度是$O(n^2 \log n)$。

到了这里简单的优化已经不能影响复杂度了,因此开始考虑数据结构。你很惊奇地发现$x_i \leq 10^6$,坐标值这么小肯定可以入手啊!结合数轴的背景,我们可以用值域线段树(权值线段树)/平衡树优化辣!

$10^6$大小的值域线段树的做法就是先把开头区间的坐标值都插进去,之后每次移动选点区间其实只会删去开头的坐标值,并插入结尾后的一个新坐标值,这样分析的话每个坐标值最多只会被插入一次和删去一次,插入的复杂度可控制在$O(n \log x_i)$内。然后对于每个区间,在当时的权值线段树中跑一边树,从根遍历到中位数所在叶子节点即可,每次找中位数的复杂度可控制在$O(\log x_i)$里。

然而找出了中位数好像还得暴力求每个点到这个中位数的距离啊?!

你又惊奇地发现,其实每个点到中位数的距离之和相当于如图的橙色线条长度之和

它相当于 坐标轴总长 减去 中位数前每个坐标到坐标轴起点的距离(坐标值)和 再减去  中位数后每个坐标到坐标轴终点的距离和。

借助上面那个值域线段树,维护每个区间内所有数 到坐标轴起点的距离之和 以及 到坐标轴终点的距离之和 即可。然后通过上述计算得到当前选点区间内所有坐标到中位数的距离。

加上外层套的二分区间长度,这样的复杂度是$O(n \log n \log x_i)$。

丧心病狂的出题人为了卡$log^2$的常数,临考试结束的时候临时取消了这题的氧气优化,然而这个复杂度好像还是能卡过

正解是$O(n \log x_i)$的。其实最后这步优化很简单,把二分区间长度套枚举起点 改为滑动窗口即可。根据上述区间答案随区间长度单调递减这个推论,从第一个点开始,当滑动窗口右端点右移到不满足条件(区间内的被选点到中位数的距离和超过 $m$)时,右移左端点缩小区间即可。滑动窗口枚举区间的复杂度是$O(n)$的,答案就是窗口长度的最大值。)

这是值域线段树做法,如果把值域线段树改成平衡树也可以维护这些,树可以只开$n$位,但是平衡树常数大,容易被卡成狗……

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #define MAXN 1048576
  5. using namespace std;
  6. inline long long read()
  7. {
  8. long long x=,t=;int c;
  9. while(!isdigit(c=getchar()))if(c=='-')t=-;
  10. while(isdigit(c))x=x*+c-'',c=getchar();
  11. return x*t;
  12. }
  13. int n;
  14. long long m;
  15. int x[MAXN];
  16. int size[<<];
  17. long long sumv[<<];
  18. void maintain(int o,int L,int R)
  19. {
  20. int m=L+R>>,lc=o<<,rc=lc|;
  21. size[o]=size[lc]+size[rc];
  22. sumv[o]=sumv[lc]+sumv[rc];
  23. }
  24. void Add(int o,int L,int R,const int pos,const int v)
  25. {
  26. if(L==R)
  27. {
  28. size[o]+=v;
  29. sumv[o]=(long long)size[o]*L;
  30. }
  31. else
  32. {
  33. int m=L+R>>,lc=o<<,rc=lc|;
  34. if(pos<=m)Add(lc,L,m,pos,v);
  35. else Add(rc,m+,R,pos,v);
  36. maintain(o,L,R);
  37. }
  38. }
  39. int GetKthPos(int o,int L,int R,const int k)
  40. {
  41. if(L==R)
  42. {
  43. return L;
  44. }
  45. else
  46. {
  47. int m=L+R>>,lc=o<<,rc=lc|;
  48. if(size[lc]>=k)return GetKthPos(lc,L,m,k);
  49. else return GetKthPos(rc,m+,R,k-size[lc]);
  50. }
  51. }
  52. long long toLeft(int o,int L,int R,const int ql,const int qr)
  53. {
  54. if(ql<=L&&R<=qr)
  55. {
  56. return sumv[o]-(long long)size[o]*ql;
  57. }
  58. else
  59. {
  60. int m=L+R>>,lc=o<<,rc=lc|;
  61. long long size=;
  62. if(ql<=m)size+=toLeft(lc,L,m,ql,qr);
  63. if(m<qr)size+=toLeft(rc,m+,R,ql,qr);
  64. return size;
  65. }
  66. }
  67. long long toRight(int o,int L,int R,const int ql,const int qr)
  68. {
  69. if(ql<=L&&R<=qr)
  70. {
  71. return (long long)size[o]*qr-sumv[o];
  72. }
  73. else
  74. {
  75. int m=L+R>>,lc=o<<,rc=lc|;
  76. long long size=;
  77. if(ql<=m)size+=toRight(lc,L,m,ql,qr);
  78. if(m<qr)size+=toRight(rc,m+,R,ql,qr);
  79. return size;
  80. }
  81. }
  82. long long CountPrice(int size)
  83. {
  84. int mid=GetKthPos(,,,(size+)>>);
  85. long long ret=;
  86. ret+=toRight(,,,,mid);
  87. ret+=toLeft(,,,mid,);
  88. return ret;
  89. }
  90. int main()
  91. {
  92. freopen("choose.in","r",stdin);
  93. freopen("choose.out","w",stdout);
  94. n=read();m=read();
  95. for(int i=;i<=n;i++)x[i]=read();
  96. int L=,R=,ans=;
  97. for(R=;R<=n;R++)
  98. {
  99. Add(,,,x[R],);
  100. while(CountPrice(R-L+)>m)
  101. Add(,,,x[L++],-);
  102. ans=max(ans,R-L+);
  103. }
  104. printf("%d",ans);
  105. return ;
  106. }

总而言之,题出的不错,就是题面写错数据卡常低分罚跑圈应该吐槽吐槽

【2018.8.10】四连测day4 题解的更多相关文章

  1. 北京化工大学2018年10月程序设计竞赛部分题解(A,C,E,H)

    目录 北京化工大学2018年10月程序设计竞赛部分题解(A,C,E,H) 竞赛事件相关 竞赛链接 竞赛题目 总结 北京化工大学2018年10月程序设计竞赛部分题解(A,C,E,H) 竞赛事件相关 竞赛 ...

  2. 四连测Day4

    四连爆炸 卡我常数 好像被AluminumGod拉到了创客...哇我这个天天爆炸的水平可能会被其他三位dalao吊起来打 orz Edmond-Karp_XiongGod orz Deidara_Wa ...

  3. 正睿 2018 提高组十连测 Day4 T3 碳

    记'1'为+1,'0'为-1; 可以发现 pre[i],suf[i]分别为前/后缀和 a[i]=max(pre[l.....i]); b[i]=max(suf[i+1....r]); ans=max( ...

  4. 算法(第四版)C#题解——2.1

    算法(第四版)C#题解——2.1   写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csh ...

  5. 申请Office 365一年免费的开发者账号攻略(2018年10月份版本)

    要进行Office 365开发,当然需要有完整的Office 365环境才可以.为了便于广大开发人员快速地启动这项工作,微软官方给所有开发人员提供了免费的一年开发者账号   那么如何申请Office ...

  6. IntelliJ IDEA 最新激活码(截止到2018年10月14日)

    IntelliJ IDEA 注册码: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUlXU1dEIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYX ...

  7. 新手C#SQL Server使用记录2018.08.10

    主键(PrimaryKey):主键就是每个数据行(记录)的唯一标识,不会有重复值的列(字段)才能当做主键.一个表可以没有主键,但是这样会很难处理表,因此一般情况表都要设置主键. 主键有两张选用策略,分 ...

  8. 01 mybatis框架整体概况(2018.7.10)-

    01 mybatis框架整体概况(2018.7.10)- F:\廖雪峰 JavaEE 企业级分布式高级架构师课程\廖雪峰JavaEE一期\第一课(2018.7.10) maven用的是3.39的版本 ...

  9. 富士康的盈利秒杀99%的A股公司:3星|《三联生活周刊》2018年10期

    三联生活周刊·最美的数学:天才为何成群到来(2018年10期) 本期专题是数学和成都,我都跳过去没看.其他内容也还有点意思. 总体评价3星. 以下是本期一些内容的摘抄,#号后面是kindle电子版中的 ...

随机推荐

  1. ubuntu 14.04 安装redis

    root@hett-PowerEdge-T30:~# sudo apt-get install redis-server Reading package lists... DoneBuilding d ...

  2. nodejs:遍历文件夹文件统计文件大小

    根据 http://blog.csdn.net/hero82748274/article/details/45700465这里的思路对读写文件做了一个 封装: webpack在打包的时候可以借助ass ...

  3. 剑指offer44 扑克牌顺序

    注意一个边界条件:必须是连续的,如果前后两个数是一样的也不满足条件 class Solution { public: bool IsContinuous( vector<int> numb ...

  4. tomcat中如何禁止和允许主机或地址访问

    1.tomcat中如何禁止和允许列目录下的文件 在{tomcat_home}/conf/web.xml中,把listings参数设置成false即可,如下: <servlet>...< ...

  5. ios 序列化

    1到底这个序列化有啥作用? 面向对象的程序在运行的时候会创建一个复杂的对象图,经常要以二进制的方法序列化这个对象图,这个过程叫做Archiving. 二进制流可以通过网络或写入文件中(来源于某教材的一 ...

  6. 【搜索 ex-BFS】bzoj2346: [Baltic 2011]Lamp

    关于图中边权非零即一的宽度优先搜索 Description 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组 ...

  7. 【Java_Spring】控制反转IOC(Inversion of Control)

    1. IOC的概念 控制反转IoC(Inversion of Control)是一种设计思想,而DI(依赖注入)是实现IoC的一种方法.在没有使用IOC的程序中,对象间的依赖关系是靠硬编码的方式实现的 ...

  8. redo log日志内容备忘

    检查点是一串递增的数字. 在两个检查点之间,存在有一个MLOG_FILE_NAME的文件,里面记录着space和路径和MLOG_CHECKPOINT的一个检查点. MLOG_FILE_NAME总是在上 ...

  9. SpringBoot 多线程

    Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程.使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor.而实际开发中任务一般是非阻 ...

  10. PAT Basic 1045

    1045 快速排序 著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的 N 个互不相同 ...