这是两个月前写的,看能不能搬运过来……

动态树是一类维护森林连通性的问题(已纠正,感谢ZQC巨佬),目前最(wo)常(zhi)见(hui)的动态树就是LCT(Link-Cut-Tree),然而LCT似乎是处理路径的,处理子树可能力不足。据说有一种称为Top Tree数据结构,可以处理所有。但是学不动了Orz
LCT中最主要的是Access操作,Access(u)操作的含义是,从当前的节点u向他所在的根节点连一条重路径,这是相当于把沿路的重路径全都断开,重新拉一条从u到根的重路径。
makeroot(x)操作:
若想让u成为当前树的根节点,则可以先access(u),再splay(u),把u转为当前splay的根节点。因为splay维护的是深度,所以u没有右儿子(没有比u还要深的点,因为重链定义),所以换根就相当于一次区间翻转,交换左右子树即完成区间翻转。此时就可以打标记了。
所以,makeroot=access+splay+rev
还有一个isroot操作,超级简单,就是判断这是不是一条重路径的根,只要他的fa指针指向的节点的左右子树都不是他(证明此时这是一条虚边),那么这就是一棵子树的根节点。
link(x,y)操作:
在u和v之间连边,可以makeroot(u),再让u的父亲为v,这就相当于v本身是一棵splay,而u和v之间连了条轻边。
cut(u,v)操作:
断开u和v之间的边,可以先makeroot(u),再access(v),再splay(v),此时v的左儿子必定为u,于是断开v和v的左儿子即可。
至于翻转标记的传递,就是跟Splay一样就行了。
但标记下放有一个问题。因为splay是时时刻刻在分裂与合并的,因为要动态维护每条重链,所以在splay之前,要先把根节点到当前节点全部下放一遍标记,防止标记下放不完全。
split(x,y)操作:
split相当于把两个子树分开,考虑到我们cut的时候第一步也是分开,所以

$split=makeroot(u)+access(v)+splay(v)$
然后还要保存一些轻边(虚边),对于轻边我们需要单独记录处理。在原树上,当前重链的顶端节点与他的父亲的边即为轻边,如果不记录,树将是不完整的。
具体到代码实现,可以是当前splay的根节点的父亲即为当前splay上面的那个重链所在的splay上的点,但上面的splay的儿子并不指向当前splay的父亲,即为用splay的根节点的父亲来存储轻边。
动态树的主要时间消耗在Access上,而Access的时间复杂度是

$O(nlogn)$
好像最后在UOJ群里看到一句话:
*树剖能做的,动态树都能做,只不过有的东西动态树做起来比树剖烦的多*
好像超级有道理,因为我写的维护子树size,树剖的话天生自带,但是LCT每次Access跳轻重边的时候都要交换,超级烦。
下面是这几天做的一点题目:
1.洞穴勘测
裸的连通性询问。

 #include<bits/stdc++.h>
#define N 10005
#define inf 1000000007
using namespace std;
int n,m;
struct Link_Cut_Tree{
int fa[N],c[N][],q[N],top;bool rev[N];
Link_Cut_Tree(){
top=;memset(fa,,sizeof(fa));
memset(c,,sizeof(c));
memset(rev,,sizeof(rev));
}
inline bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
inline void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[x]^=;rev[l]^=;rev[r]^=;
swap(c[x][],c[x][]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][]==x);r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t;}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){makeroot(x);fa[x]=y;splay(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);c[y][]=fa[x]=;}
int find(int x){
access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;
}
}T;
inline int read(){
int x=,f=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
char s[];int x,y;
n=read();m=read();
for(int i=;i<=m;i++){
scanf("%s",s);
x=read();y=read();
if(s[]=='C')T.link(x,y);
if(s[]=='D')T.cut(x,y);
if(s[]=='Q'){
int xx=T.find(x),yy=T.find(y);
if(xx==yy)puts("Yes");else puts("No");
}
}
return ;
}

2.bzoj1180 OTOCI
修改,连边,区间权值合。
其实可以先读入所有的边得到最后的树,然后离线树剖,用并查集维护边就行了
本蒟蒻还是写了Link-Cut-Tree

 #include<bits/stdc++.h>
#define N 30005
#define inf 1000000000
#define yql 1000000007
#define ll long long
using namespace std;
int q,n;
struct Link_Cut_Tree{
int c[N][],fa[N],sumv[N],val[N],q[N],top[N];
bool rev[N];
void pushup(int x){
int l=c[x][],r=c[x][];sumv[x]=sumv[l]+sumv[r]+val[x];
}
void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[x]^=;rev[r]^=;rev[l]^=;
swap(c[x][],c[x][]);
}
}
bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][]==x);r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){makeroot(x);fa[x]=y;}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);c[y][]=fa[x]=;}
int find(int x){
access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;
}
}T;
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
n=read();
for(int i=;i<=n;i++){T.sumv[i]=read();T.val[i]=T.sumv[i];}
q=read();char s[];
while(q--){
scanf("%s",s);int x=read(),y=read();
if(s[]=='b'){
int xx=T.find(x),yy=T.find(y);
if(xx==yy)puts("no");
else puts("yes"),T.link(x,y);
}
if(s[]=='p')T.makeroot(x),T.val[x]=y,T.pushup(x);
if(s[]=='e'){
int xx=T.find(x),yy=T.find(y);
if(xx!=yy)puts("impossible");
else{
T.makeroot(x);T.access(y);T.splay(y);
printf("%d\n",T.sumv[y]);
}
}
}
return ;
}

3.NOI2014 膜法森林
考虑Kruskal求出最小生成树,每次加,如果当前的边成环,那么就在之前的边里找一个最大权的cut掉。
维护连通性,cut边,最大值询问,LCT很擅长啦~

 #include<bits/stdc++.h>
#define inf 1000000007
#define N 200005
using namespace std;
int n,m,cnt,_=inf;
int f[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
struct Edge{
int u,v,w,c;
bool operator<(const Edge &x)const{return w<x.w;}
}G[*N]; struct Link_Cut_Tree{
int c[N][],fa[N],q[N],rev[N],top;
int maxv[N],val[N];
inline void pushup(int x){
int l=c[x][],r=c[x][];
maxv[x]=x;
if(val[maxv[l]]>val[maxv[x]])maxv[x]=maxv[l];
if(val[maxv[r]]>val[maxv[x]])maxv[x]=maxv[r];
}
Link_Cut_Tree(){top=;memset(rev,,sizeof(rev));}
bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[l]^=;rev[r]^=;rev[x]^=;
swap(c[x][],c[x][]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][])==x;r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){makeroot(x);fa[x]=y;splay(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);c[y][]=fa[x]=;pushup(y);}
int find(int x){access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;}
int querymax(int x,int y){split(x,y);return maxv[y];}
};
Link_Cut_Tree T;
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
n=read();m=read();
for(int i=;i<=n+;i++)f[i]=i;
for(int i=;i<=m;i++){
G[i].u=read(),G[i].v=read(),G[i].w=read();G[i].c=read();
}
sort(G+,G+m+);
int tot=;
for(int i=;i<=m;i++){
int u=G[i].u,v=G[i].v,w=G[i].w,c=G[i].c;
if(find(u)==find(v)){
int t=T.querymax(u,v);
if(T.val[t]>G[i].c){
T.cut(t,G[t-n].u);
T.cut(t,G[t-n].v);
}
else {
if(find()==find(n))_=min(_,G[i].w+T.val[T.querymax(,n)]);
continue;
}
}
else f[find(u)]=find(v);
T.val[n+i]=G[i].c;T.maxv[n+i]=n+i;
T.link(u,n+i);T.link(v,n+i);
if(find()==find(n))_=min(_,G[i].w+T.val[T.querymax(,n)]);
}
if(_==inf)puts("-1");else printf("%d\n",_);
return ;
}

4.uoj 共价大爷游长沙
%%%%毛爷爷,不看题解不会系列。
这题做的极其艰辛:
1.zcy:我怎么维护子树size啊…………啊………………
想了半个下午,我好像会了!去机房写!
2.zcy:我的权值怎么这么小啊,都是几十几十的东西……
wori,随机数种子选的有毒?我去uoj上找一个吧……
3.zcy:我的link怎么权值改的那么鬼啊?我看看……
wori,cut写错了,mdzz。
代码准确度啊……

#include<bits/stdc++.h>
#define N 300100
using namespace std;
int n,m,x,y,z;
struct Link_Cut_Tree{
int c[N][],q[N],fa[N],size[N],top,rev[N],val[N],sumv[N];
int a[N],b[N],w[N],sum;
inline bool isroot(int x){return fa[x]==||c[fa[x]][]!=x&&c[fa[x]][]!=x;}
inline void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[l]^=;rev[r]^=;rev[x]^=;
swap(c[x][],c[x][]);
}
}
void pushall(int x){
if(!isroot(x))pushall(fa[x]);pushdown(x);
}
inline void pushup(int x){
sumv[x] = val[x]^sumv[c[x][]]^sumv[c[x][]];
}
void rotate(int x){
int y = fa[x],g=fa[y],ch=c[y][]==x;
if (!isroot(y))c[g][c[g][]==y]=x;
c[y][ch]=c[x][!ch],fa[c[y][ch]]=y;
fa[y] =x,fa[x]=g,c[x][!ch] = y;
pushup(y);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
pushup(x);
}
void access(int x){
for(int t=;x;t=x,x=fa[x]){
splay(x);val[x]^=sumv[t]^sumv[c[x][]];
c[x][]=t;pushup(x);
}
}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){
makeroot(x);makeroot(y);fa[x]=y;val[y]^=sumv[x];pushup(y);
}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){
makeroot(y);access(y);splay(x);fa[x]=;val[y]^=sumv[x];pushup(y);
}
void change(int x,int v){access(x);splay(x);val[x]^=v;pushup(x);}
}T; struct Edge{
int u;int v;int w;
Edge(int a=,int b=,int c=){u=a;v=b;w=c;}
}G[*N];
inline int read(){
int x=,f=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
int id;
id=read();n=read();m=read();
srand(time(NULL));
for(int i=;i<n;i++){
x=read(),y=read();
T.link(x,y);
}x=;y=;
int tot=,res=;
while(m--){
int opt=read(),x,y,u,v;
if(opt==){
x=read();y=read();u=read();v=read();
T.cut(x,y);T.link(u,v);//printf("%d\n",T.val[v]);
}
else if(opt==){
int k=rand();
x=read(),y=read();while(!k)k=rand();
G[++tot]=Edge(x,y,k);res^=k;
T.change(x,k);T.change(y,k);
//printf("%d\n",T.val[y]);
}
else if(opt==){
x=read();
res^=G[x].w;
T.change(G[x].u,G[x].w);T.change(G[x].v,G[x].w);
}
else if(opt==){
x=read();y=read();
T.makeroot(x);T.access(y);
if(T.val[y]==res)puts("YES");
else puts("NO");
}
//printf("%d\n",res);printf("%d\n",T.val[y]);
}
return ;
}

不开心,这个快把我写死的LCT居然只有100行
5.ZJOI2012 网络
这题如果单看每种颜色,我们只要建一个LCT就能轻松水过去,无非是要加个cnt
但是颜色多怎么办?考虑颜色种类很小,我们多建几个LCT不就行了么?

 #include<bits/stdc++.h>
#define N 10005
#define M 100005
using namespace std;
int n, m, c, k, u, v, w, op, x,val[N];
struct Link_Cut_Tree{
int c[N][],fa[N],rev[N],maxv[N],cnt[N],q[N];
inline void pushup(int x){
maxv[x]=val[x];int l=c[x][],r=c[x][];
if(l)maxv[x]=max(maxv[x],maxv[l]);
if(r)maxv[x]=max(maxv[x],maxv[r]);
}
inline void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[l]^=;rev[r]^=;rev[x]^=;
swap(c[x][],c[x][]);
}
}
bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][])==x;r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){cnt[x]++;cnt[y]++;makeroot(x);fa[x]=y;splay(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);cnt[x]--;cnt[y]--;c[y][]=fa[x]=;pushup(y);}
int find(int x){access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;}
int querymax(int x,int y){split(x,y);return maxv[y];}
}lct[];
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
struct Edge{
int u,v;
bool operator<(const Edge &x)const{if(u!=x.u)return u<x.u;
else return v<x.v;}
};
map<Edge,int> mp;
int main(){
n=read();m=read();c=read();k=read();
for(int i=;i<=n;i++)val[i]=read();
for(int i=;i<=m;i++){
int u=read(),v=read(),w=read();
w++;
Edge e1=(Edge){u,v},e2=(Edge){v,u};
mp[e1]=mp[e2]=w;
lct[w].link(u,v);
}
while(k--){
int opt=read();
if(opt==){
int x=read(),w=read();
val[x]=w;
for(int i=;i<=c;i++)lct[i].splay(x);
}
else if(opt==){
int u=read(),v=read(),w=read();
w++;
Edge a=(Edge){u,v},b=(Edge){v,u};
if(!mp.count(a)){
puts("No such edge.");continue;
}
int xxx=mp[a];
if(xxx==w){
puts("Success.");continue;
}
if(lct[w].cnt[u]>=||lct[w].cnt[v]>=){
puts("Error 1.");continue;
}
if(lct[w].find(u)==lct[w].find(v)){
puts("Error 2.");continue;
}
puts("Success.");
lct[xxx].cut(u,v);lct[w].link(u,v);
mp[a]=mp[b]=w;
}else{
int w=read(),u=read(),v=read();
w++;
if(lct[w].find(u)!=lct[w].find(v)){
puts("-1");continue;
}
printf("%d\n",lct[w].querymax(u,v));
}
}
return ;
}

【学习笔记】动态树Link-Cut-Tree的更多相关文章

  1. 动态树(Link Cut Tree) :SPOJ 375 Query on a tree

    QTREE - Query on a tree #number-theory You are given a tree (an acyclic undirected connected graph) ...

  2. 【学习笔记】LCT link cut tree

    大概就是供自己复习的吧 1. 细节讲解 安利两篇blog: Menci 非常好的讲解与题单 2.模板 把 $ rev $ 和 $ pushdown $ 的位置记清 #define lc son[x][ ...

  3. 学习笔记-动态树Link-Cut-Tree

    --少年你有梦想吗? --少年你听说过安利吗? 安利一个集训队讲解:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb 关于动态树问题,有多种方法 ...

  4. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  5. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  6. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  7. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  8. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  9. 学习笔记:Link Cut Tree

    模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...

  10. LG3690 【模板】Link Cut Tree (动态树)

    题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...

随机推荐

  1. HTML5 Web SQL 数据库总结

    Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs. 如果你是一个 Web 后端程序员,应该很容易理解 SQ ...

  2. BZOJ4300 绝世好题(动态规划)

    设f[i][j]为前i个数中所选择的最后一个数在第j位上为1时的最长序列长度,转移显然. #include<iostream> #include<cstdio> #includ ...

  3. CF995A Tesla

    题目描述 Allen dreams of one day owning a enormous fleet of electric cars, the car of the future! He kno ...

  4. Linux(ubuntu 12.04桌面版) 搭建Android开发环境

    因为一些工作上的原因,需要切换到Linux环境下做点开发,我选择的Linux发行版本为ubuntu(我不建议使用fedora,我最开始就是使用的fedora,但发现并不是特别好使,有些插件没办法安装, ...

  5. Android 动画之View动画效果和Activity切换动画效果

    View动画效果: 1.>>Tween动画通过对View的内容进行一系列的图形变换(平移.缩放.旋转.透明度变换)实现动画效果,补间动画需要使用<set>节点作为根节点,子节点 ...

  6. Android View 绘制刷新流程分析

    Android中对View的更新有很多种方式,使用时要区分不同的应用场合.1.不使用多线程和双缓冲      这种情况最简单,一般只是希望在View发生改变时对UI进行重绘.你只需显式地调用View对 ...

  7. 全面解析JavaScript的Backbone.js框架中的Router路由

    这篇文章主要介绍了Backbone.js框架中的Router路由功能,Router在Backbone中相当于一个MVC框架中的Controller控制器功能,需要的朋友可以参考下. Backbone ...

  8. JSP页面中的Meta标签详解

    Meta标签详解 相信大家在平时开发中最常接触的页面就是html和jsp了,可在这两个页面中有一个Meta标签你天天都会看见,可是你真的了解这个标签的一些其他用处吗?今天给大家介绍一些该标签的其他应用 ...

  9. JAVA对象的深度克隆

    有时候,我们需要把对象A的所有值复制给对象B(B = A),但是这样用等号给赋值你会发现,当B中的某个对象值改变时,同时也会修改到A中相应对象的值! 也许你会说,用clone()不就行了?!你的想法只 ...

  10. Qt中内存泄露和退出崩溃的问题 delete

    Qt中帮程序员做了一些内存回收的事情,但正因为这些反而让对此不熟悉的人会屡屡犯错. 收录一篇不错的文章: 在C++中学习过程中,我们都知道: delete 和 new 必须 配对使用(一 一对应):d ...