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

Link-cut-tree是一种维护动态森林的数据结构,在需要动态加边/删边的时候就需要LCT来维护。

Link-cut-tree的核心是轻重链划分,每条重链用一颗splay来维护。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct LCT{
int son[2][100005],fa[100005],siz[100005],val[100005];
inline void pushup(int x){siz[x]=siz[son[0][x]]^siz[son[1][x]]^val[x];}
bool rev[100005];
inline void pushdown(int x){
if(!rev[x])return ;
rev[son[0][x]]^=1;rev[son[1][x]]^=1;
swap(son[0][x],son[1][x]);rev[x]=0;
}
inline bool isroot(int x){
return !(son[0][fa[x]]==x||son[1][fa[x]]==x);
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
if(!isroot(y))son[y==son[1][z]][z]=x;
bool is=(son[1][y]==x);
son[is][y]=son[!is][x];fa[son[!is][x]]=y;
son[!is][x]=y;fa[y]=x;fa[x]=z;pushup(y);pushup(x);
}
int stk[100005],top;
inline void splay(int x){
stk[++top]=x;
for(int i=x;!isroot(i);i=fa[i])stk[++top]=fa[i];
while(top)pushdown(stk[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];//cout<<x<<" "<<y<<" "<<z<<endl;
if(!isroot(y)){
if((son[1][y]==x)^(son[1][z]==y))rotate(x);
else rotate(y);
}rotate(x);
}
}
inline void access(int x){
for(int i=0;x;i=x,x=fa[x])splay(x),son[1][x]=i,pushup(x);
}
inline void makert(int x){
access(x);splay(x);rev[x]^=1;
}
inline int find(int x){
access(x);splay(x);while(son[0][x])x=son[0][x];
return x;
}
inline void link(int x,int y){
if(find(x)==find(y))return ;
makert(x);fa[x]=y;
}
inline void split(int x,int y){
makert(x);access(y);splay(y);
}
inline void cut(int x,int y){
split(x,y);
if(son[0][y]==x&&son[1][x]==0)son[0][y]=fa[x]=0;
}
}T;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&T.val[i]),T.siz[i]=T.val[i];
while(m--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==0)T.split(x,y),printf("%d\n",T.siz[y]);
if(op==1)T.link(x,y);
if(op==2)T.cut(x,y);
if(op==3)T.makert(x),T.val[x]=y,T.pushup(x);
} return 0;
}

【模板】最近公共祖先(LCA)

\(LCT\) 也是一种求 \(lca\) 的方法法,而且好像比倍增快

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m,s;
int son[2][500005],fa[500005];
bool rev[500005];
inline void down(int x){
if(rev[x]){
swap(son[0][x],son[1][x]);
rev[son[0][x]]^=1;rev[son[1][x]]^=1;
}rev[x]=0;
}
inline bool isroot(int x){
return son[1][fa[x]]!=x&&son[0][fa[x]]!=x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
if(!isroot(y))son[y==son[1][z]][z]=x;
bool is=(son[1][y]==x);
son[is][y]=son[!is][x];fa[son[!is][x]]=y;
son[!is][x]=y;fa[x]=z;fa[y]=x;
}
int stk[500005],top;
inline void splay(int x){
stk[++top]=x;
for(int y=x;!isroot(y);y=fa[y])stk[++top]=fa[y];
while(top)down(stk[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((son[1][y]==x)^(son[1][z]==y))rotate(x);
else rotate(y);
}rotate(x);
}
}
inline int access(int x){
int i=0;
for(;x;i=x,x=fa[x])splay(x),son[1][x]=i;
return i;
}
inline void makert(int x){
access(x);splay(x);rev[x]^=1;
}
inline void link(int x,int y){
makert(x);fa[x]=y;
}
inline void split(int x,int y){
makert(x);access(y);splay(y);
}
inline void cut(int x,int y){
split(x,y);son[0][y]=fa[x]=0;
}
inline int find(int x){
access(x);splay(x);while(son[0][x])x=son[0][x];
return x;
}
inline int lca(int x,int y){
access(x);splay(x);
return access(y);
}
int main(){
scanf("%d%d%d",&n,&m,&s);
son[0][0]=son[1][0]=-1;
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
link(x,y);
}makert(s);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
} return 0;
}

[SDOI2008] 洞穴勘测

又是一个模板,不过好像可以暴力水过去

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int son[2][10005],fa[10005];
bool rev[10005];
inline void down(int x){
if(rev[x]){
swap(son[0][x],son[1][x]);
rev[son[0][x]]^=1;rev[son[1][x]]^=1;
}rev[x]=0;
}
inline bool isroot(int x){
return son[1][fa[x]]!=x&&son[0][fa[x]]!=x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
if(!isroot(y))son[y==son[1][z]][z]=x;
bool is=(son[1][y]==x);
son[is][y]=son[!is][x];fa[son[!is][x]]=y;
son[!is][x]=y;fa[x]=z;fa[y]=x;
}
int stk[10005],top;
inline void splay(int x){
stk[++top]=x;
for(int y=x;!isroot(y);y=fa[y])stk[++top]=fa[y];
while(top)down(stk[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((son[1][y]==x)^(son[1][z]==y))rotate(x);
else rotate(y);
}rotate(x);
}
}
inline void access(int x){
for(int i=0;x;i=x,x=fa[x])splay(x),son[1][x]=i;
}
inline void makert(int x){
access(x);splay(x);rev[x]^=1;
}
inline void link(int x,int y){
makert(x);fa[x]=y;
}
inline void split(int x,int y){
makert(x);access(y);splay(y);
}
inline void cut(int x,int y){
split(x,y);son[0][y]=fa[x]=0;
}
inline int find(int x){
access(x);splay(x);while(son[0][x])x=son[0][x];
return x;
}
char op[15];
int main(){
scanf("%d%d",&n,&m);
son[0][0]=son[1][0]=-1;
while(m--){
int x,y;
scanf("%s%d%d",op,&x,&y);
if(op[0]=='Q')puts(find(x)==find(y)?"Yes":"No");
if(op[0]=='C')link(x,y);
if(op[0]=='D')cut(x,y);
} return 0;
}

[NOI2014] 魔法森林

\(LCT\) 想维护边上信息,只需对每条边开一个点出来即可

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int son[2][200005],fa[200005];
bool rev[200005];
struct node{
int x,y,a,b,id;
node(){}
node(int _x,int _y,int _a,int _b,int _id){
x=_x;y=_y;a=_a;b=_b;id=_id;
}
inline bool operator <(const node &b)const{
return a<b.a;
}
}val[200005],sm[200005];
inline node cmp(node x,node y){
return x.b<y.b?y:x;
}
inline void pushup(int x){
sm[x]=val[x];
sm[x]=cmp(sm[x],sm[son[0][x]]);
sm[x]=cmp(sm[x],sm[son[1][x]]);
}
inline void down(int x){
if(rev[x]){
swap(son[0][x],son[1][x]);
rev[son[0][x]]^=1;rev[son[1][x]]^=1;
}rev[x]=0;
}
inline bool isroot(int x){
return son[0][fa[x]]!=x&&son[1][fa[x]]!=x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
if(!isroot(y))son[son[1][z]==y][z]=x;
bool is=(son[1][y]==x);
son[is][y]=son[!is][x];fa[son[!is][x]]=y;
son[!is][x]=y;fa[x]=z;fa[y]=x;pushup(y);pushup(x);
}
int stk[200005],top;
inline void splay(int x){
stk[++top]=x;
for(int i=x;!isroot(i);i=fa[i])stk[++top]=fa[i];
while(top)down(stk[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((son[1][y]==x)^(son[1][z]==y))rotate(x);
else rotate(y);
}rotate(x);
}
}
inline void access(int x){
for(int i=0;x;i=x,x=fa[x])splay(x),son[1][x]=i,pushup(x);
}
inline void makert(int x){
access(x);splay(x);rev[x]^=1;
}
inline void link(int x,int y){
makert(x);splay(x);fa[x]=y;
}
inline void cut(int x,int y){
makert(x);splay(x);access(y);splay(y);
son[0][y]=fa[x]=0;pushup(y);
}
inline node select(int x,int y){
makert(x);splay(x);access(y);splay(y);
return sm[y];
}
inline int find(int x){
access(x);splay(x);for(down(x);son[0][x];down(x))x=son[0][x];
return x;
}
vector<node> vec;
int ans=2e9;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y,a,b;
scanf("%d%d%d%d",&x,&y,&a,&b);if(x==y)continue;
val[n+i]=node(x,y,a,b,i+n);vec.push_back(val[n+i]);
}son[0][0]=son[1][0]=-1;
sort(vec.begin(),vec.end());
for(auto it:vec){
if(find(it.x)!=find(it.y))link(it.id,it.x),link(it.id,it.y);
else {
node u=select(it.x,it.y);
if(u.b>it.b){
cut(u.x,u.id);cut(u.y,u.id);
link(it.x,it.id);link(it.y,it.id);
}
}
if(find(1)==find(n)){
ans=min(ans,it.a+select(1,n).b);
}
}
printf("%d",ans==2e9?-1:ans); return 0;
}

[BJOI2014]大融合

把 \(access\) 改一下,再注意一下更新时 \(splay\) 的形态,就可以用\(LCT\) 维护虚子树信息

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,q;
int son[2][100005],fa[100005],siz[100005],val[100005];
bool rev[100005];
inline void pushup(int x){
siz[x]=siz[son[0][x]]+val[x]+siz[son[1][x]];
}
inline void down(int x){
if(rev[x]){
swap(son[0][x],son[1][x]);
rev[son[0][x]]^=1;rev[son[1][x]]^=1;
}rev[x]=0;
}
inline bool isroot(int x){
return son[1][fa[x]]!=x&&son[0][fa[x]]!=x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
if(!isroot(y))son[son[1][z]==y][z]=x;
bool is=(son[1][y]==x);
son[is][y]=son[!is][x];fa[son[!is][x]]=y;
son[!is][x]=y;fa[x]=z;fa[y]=x;pushup(y);pushup(x);
}
int stk[100005],top;
inline void splay(int x){
stk[++top]=x;
for(int i=x;!isroot(i);i=fa[i])stk[++top]=fa[i];
while(top)down(stk[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((son[1][y]==x)^(son[1][z]==y))rotate(x);
else rotate(y);
}rotate(x);
}
}
inline void access(int x){
for(int i=0;x;i=x,x=fa[x]){
splay(x);val[x]+=siz[son[1][x]];
son[1][x]=i;val[x]-=siz[i];pushup(x);
}
}
inline void makert(int x){
access(x);splay(x);rev[x]^=1;
}
inline void link(int x,int y){
makert(x);makert(y);fa[x]=y;
val[y]+=siz[x];pushup(y);
}
inline void cut(int x,int y){
makert(x);access(y);splay(y);
son[0][y]=fa[x]=0;pushup(x);pushup(y);(x);makert(y);
}
inline int query(int x){
access(x);splay(x);
return siz[x];
}
char op[2];
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)siz[i]=val[i]=1;
while(q--){
int x,y;
scanf("%s%d%d",op,&x,&y);
if(op[0]=='A')link(x,y);
else {
cut(y,x);
printf("%lld\n",1ll*query(x)*query(y));
link(x,y);
}
} return 0;
}

【模板】 "动态DP"&动态树分治(加强版)

对于静态树,可以将 \(splay\) 静态化为一颗普通 \(BST\) ,称为 “全局平衡二叉树”

点击查看代码
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
using namespace std;
int n,m;
const int SIZE=(1<<21)+1;
char ibuf[SIZE],*iS=ibuf,*iT=ibuf;
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
template <class T>
void read(T &x){
int f=0;x=0;char c=gc();
while(!isdigit(c)) f|=c=='-',c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
if(f) x=-x;
}
int ver[2000005],ne[2000005],head[1000005],cnt;
inline void link(int x,int y){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;
}
int siz[1000005],son[1000005];
void dfs(int x,int fi){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
dfs(u,x);siz[x]+=siz[u];
if(siz[u]>siz[son[x]])son[x]=u;
}
}
struct mat{
int a[2][2];
mat(int _x=0,int _y=0){a[0][0]=a[1][1]=_x;a[0][1]=a[1][0]=_y;}
inline int* operator [](int t){
return a[t];
}
inline mat operator *(mat &b){
mat res(-1e9,-1e9);
for(int i=0;i<2;i++){
for(int t=0;t<2;t++){
for(int j=0;j<2;j++)res[i][j]=max(res[i][j],a[i][t]+b[t][j]);
}
}return res;
}
inline mat operator +(mat &b){
mat res=*this;int tmp=max(b[0][0],b[1][0]);
res[0][0]+=tmp;res[0][1]+=tmp;res[1][0]+=b[0][0];
return res;
}
inline mat operator -(mat &b){
mat res=*this;int tmp=max(b[0][0],b[1][0]);
res[0][0]-=tmp;res[0][1]-=tmp;res[1][0]-=b[0][0];
return res;
}
}val[1000005],tree[1000005];
int le[1000005],ri[1000005],stk[1000005],top;
inline void pushup(int x){
tree[x]=tree[le[x]]*val[x]*tree[ri[x]];
}
int fa[1000005];
int build(int x,int l,int r){
int all=0,sum=0;
for(int i=l;i<=r;i++)all+=siz[stk[i]]-siz[son[stk[i]]];
for(int i=l;i<=r;i++){
sum+=siz[stk[i]]-siz[son[stk[i]]];
if(sum>=all/2){
le[stk[i]]=build(stk[i],l,i-1);ri[stk[i]]=build(stk[i],i+1,r);fa[stk[i]]=x;
pushup(stk[i]);return stk[i];
}
}return 0;
}
bool vis[1000005];
int solve(int x,int fi=0){
for(int y=x;y;y=son[y])vis[y]=1;
for(int y=x;y;y=son[y]){
for(int i=head[y];i;i=ne[i]){
int u=ver[i];
if(!vis[u]){
int z=solve(u,y);
val[y]=val[y]+tree[z];
}
}
}top=0;
for(int y=x;y;y=son[y])stk[++top]=y;
return build(fi,1,top);
}
int a[1000005];
inline bool isroot(int x){
return le[fa[x]]!=x&&ri[fa[x]]!=x;
}
inline void update(int x,int y){
val[x][1][0]+=y-a[x];a[x]=y;
while(x){
if(isroot(x)&&fa[x])val[fa[x]]=val[fa[x]]-tree[x];
pushup(x);
if(isroot(x)&&fa[x])val[fa[x]]=val[fa[x]]+tree[x];
x=fa[x];
}
}
int ans,rt;
int main(){
read(n);read(m);
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1;i<n;i++){
int x,y;read(x);read(y);
link(x,y);link(y,x);
}
dfs(1,1);
val[0]=tree[0]=mat(0,-1e9);
for(int i=1;i<=n;i++){
val[i][1][0]=a[i];
val[i][1][1]=-1e9;
}rt=solve(1,0);
while(m--){
int x,y;read(x);read(y);x^=ans;
update(x,y);
printf("%d\n",ans=max(tree[rt][0][0],tree[rt][1][0]));
} return 0;
}

#1220. 地平线

由于 \(splay\) 有均摊分析,最好每访问一个节点就 \(splay\) 一次,而不是只 \(splay\) 需要变为根的节点,保证复杂度

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m,q,cnt;
int mpx[3000005],mpy[3000005];
int son[2][3000005],fa[3000005];
inline bool isroot(int x){
return son[0][fa[x]]!=x&&son[1][fa[x]]!=x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
if(!isroot(y))son[son[1][z]==y][z]=x;
bool is=(son[1][y]==x);
son[is][y]=son[!is][x];fa[son[is][y]]=y;
son[!is][x]=y;fa[y]=x;fa[x]=z;
}
inline void splay(int x){
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((son[1][y]==x)^(son[1][z]==y))rotate(x);
else rotate(y);
}rotate(x);
}
}
inline void access(int x){
for(int i=0;x;i=x,x=fa[x])splay(x),son[1][x]=i;
}
inline void cut(int x){
access(x);splay(x);fa[son[0][x]]=0;son[0][x]=0;
}
inline int findrt(int x){
access(x);splay(x);
while(son[0][x])x=son[0][x];splay(x);
return x;
}
inline void link(int x,int y){
// cout<<"link ("<<mpx[x]<<" "<<mpy[x]<<") ("<<mpx[y]<<" "<<mpy[y]<<")\n";
access(x);splay(x);fa[x]=y;
}
int dsu[3000005];
inline void update(int x,int y){
int F=findrt(x);cut(x);
if(dsu[F]&&findrt(dsu[F])!=F)link(F,dsu[F]);
dsu[x]=y;
if(findrt(y)!=x)link(x,y);
}
vector<int> mp[1000005];
char s[1000005],op[3];
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=0;i<=n+1;i++){
mp[i].resize(m+2);
for(int j=0;j<=m+1;j++){
mp[i][j]=++cnt;
if(i==0||i==n+1||j==0||j==m+1)mpx[cnt]=i,mpy[cnt]=j;
else mpx[cnt]=-1,mpy[cnt]=-1;
}
}
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
if(s[j]=='>')update(mp[i][j],mp[i][j+1]);
else if(s[j]=='<')update(mp[i][j],mp[i][j-1]);
else update(mp[i][j],mp[i-1][j]);
}
}
while(q--){
int x,y;char c[2];
scanf("%s%d%d",op,&x,&y);
if(op[0]=='q'){
int F=findrt(mp[x][y]);
printf("%d %d\n",mpx[F],mpy[F]);
}else {
scanf("%s",c);
if(c[0]=='>')update(mp[x][y],mp[x][y+1]);
else if(c[0]=='<')update(mp[x][y],mp[x][y-1]);
else if(c[0]=='^')update(mp[x][y],mp[x-1][y]);
}
} return 0;
}

动态树 — Link_Cut_Tree的更多相关文章

  1. 【学习笔记】动态树Link-Cut-Tree

    这是两个月前写的,看能不能搬运过来…… 动态树是一类维护森林连通性的问题(已纠正,感谢ZQC巨佬),目前最(wo)常(zhi)见(hui)的动态树就是LCT(Link-Cut-Tree),然而LCT似 ...

  2. BZOJ2759: 一个动态树好题

    BZOJ2759: 一个动态树好题 Description 有N个未知数x[1..n]和N个等式组成的同余方程组:x[i]=k[i]*x[p[i]]+b[i] mod 10007其中,k[i],b[i ...

  3. Link Cut Tree 动态树 小结

    动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...

  4. HDU 4010 Query on The Trees (动态树)(Link-Cut-Tree)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一 ...

  5. 如何利用FineReport制作动态树报表

    在对数据字段进行分类管理时,利用动态树折叠数据是一个很好的方法,也就是点击数据前面的加号才展开对应下面的数据,如下图.那这样的效果在制作报表时该如何实现呢? 下面以报表工具FineReport为例介绍 ...

  6. 动态树之LCT(link-cut tree)讲解

    动态树是一类要求维护森林的连通性的题的总称,这类问题要求维护某个点到根的某些数据,支持树的切分,合并,以及对子树的某些操作.其中解决这一问题的某些简化版(不包括对子树的操作)的基础数据结构就是LCT( ...

  7. 【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)

    3589: 动态树 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 405  Solved: 137[Submit][Status][Discuss] ...

  8. BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...

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

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

随机推荐

  1. Android四大组件——Activity——Activity之间通信下

    显式意图:一般是用于应用内组件跳转.(如从ActivityA跳转到ActivityB) 隐式意图:一半用于应用之间的跳转.(如从ActivityA跳转到拨号) 隐式意图跳转到百度: 只需将前面Main ...

  2. 企业级 Web 开发的挑战

    本文翻译自土牛Halil ibrahim Kalkan的<Mastering ABP Framework>,是系列翻译的起头,适合ABP开发人员或者想对ABP框架进行深入演进的准架构师. ...

  3. [AcWing 75] 和为S的两个数字

    点击查看代码 class Solution { public: vector<int> findNumbersWithSum(vector<int>& nums, in ...

  4. [总结] 零散的 tricks

    对于类似构造方案的题目,先确定其中一些关键位置的方案,然后看是否能较为简单地推出其他位置的方案. 一个长度为 \(n\) 的序列,满足 \[a_1\le-a_4\le a_7\le-a_{10}\le ...

  5. Vue.js 3.x 双向绑定原理

    什么是双向绑定? 废话不多说,我们先来看一个 v-model 基本的示例: <input type="text" v-model="search"> ...

  6. 深度解析javaScript常见数据类型检查校验

    前言 在JavaScript中,数据类型分为两大类,一种是基础数据类型,另一种则是复杂数据类型,又叫引用数据类型 基础数据类型:数字Number 字符串String 布尔Boolean Null Un ...

  7. Java编程小技巧(1)——方法传回两个对象

    原文地址:Java编程小技巧(1)--方法传回两个对象 | Stars-One的杂货小窝 题目是个伪命题,由Java语法我们都知道,方法要么返回一个对象,要么就不返回 当有这样的情况,我们需要返回两个 ...

  8. mySql in 语句查询优化

    有这么一条sql UPDATE product set BuyerCount =BuyerCount+1 where ProductId in( SELECT ProductId from order ...

  9. JavaScript中if语句优化和部分语法糖小技巧推荐

    前言 在前端日常开发过程中,if else判断语句使用的次数应该是比较频繁的了,一些较为复杂的场景,可能会用到很多判断,在某个代码块使用很多if else时,代码会显得较为冗余,阅读起来不够清晰. 除 ...

  10. 一起看 I/O | Flutter 休闲游戏工具包发布

    作者 / Zoey Fan, Product Manager for Flutter, Google 对于大多数开发者来说,Flutter 是一个应用框架.但利用 Flutter 提供的硬件加速图形支 ...