前言
这篇博文主要记录一下我对自己代码风格的改善。
代码风格的改善一般还是为了休闲, 但有时其带来的收益确实是巨大的,
我个人认为绝大多数情况下收益体现在常数、编码难度和代码阅读舒适度上。
基本 style
if-else语句和三目运算符
基本
参考 这篇文章, 两者的效率似乎没有差别;参考 这篇文章, 得知上篇文章似乎默认编译器开启了优化。
对于 if-else, 似乎有个叫做分支预测的东西使得这个语句要有上界为 14 的时钟周期, 而三目运算符只有 4。(这一句话是凭着模糊的记忆写出来的, 大可不看)
即使 if-else 和三目运算符有着几乎相同的效率, 我还是喜欢使用三目运算符。
要注意的是三目运算符似乎不能返回 void
类型, 所以在里面塞函数的时候要注意最后要加个 0。
例如:这段代码可以正常运行, 输出结果是 4
#include<bits/stdc++.h>
using namespace std;
void fuc1(int &x) {x += 1;}
void fuc2(int &x) {x += 2;}
int main() {
int a = 1;
// if(a==1) fuc1(a), fuc2(a);
a==1 ? fuc1(a),fuc2(a),0 :0;
cout << a;
return 0;
}
实际上, 三目运算符可以在一定程度上代替 if-else 语句的本质是逗号表达式的性质, 参考自 这篇文章。
三目运算符不能代替如下 if语句:
if(x) return;
if(X) continue;
if(P) break;
其它的我就不知道了。
一点小 trick
短语句前置
这个 trick 的意思是, 这样的一个分支:
if(x) {
o o o o
o o o o
} else o o;
要改成三目运算符的话, !x ? o o : o o o o o o o o;
有时会比 x ? o o o o o o o o : x
写起来好看, 特别是分支有嵌套的时候。
比如:
int Merge(int a, int b)
{
return
a&&b
?
mx(a)<mx(b)?a^=b^=a^=b:0,
rc(a) = Merge(rc(a),b),
npl(lc(a))<npl(rc(a))
?
lc(a)^=rc(a)^=lc(a)^=rc(a)
:0,
npl(a) = npl(rc(a))+1,
a
:a|b;
}
int Merge(int a, int b) {
return !a||!b ? a|b :
mx(a)<mx(b)?a^=b^=a^=b:0,
rc(a) = Merge(rc(a),b),
npl(lc(a))<npl(rc(a)) ? lc(a)^=rc(a)^=lc(a)^=rc(a):0,
npl(a) = npl(rc(a))+1,
a
}
当然, 实际上没啥卵用。
尝试改善代码阅读体验
1
// 修改前
#include<bits/stdc++.h>
using namespace std;
const int Mn = 2e5+3;
int n,K;
int ct, hd[Mn], nt[Mn*2+1], vr[Mn*2+1], w[Mn*2+1];
void ad(int x, int y, int z) {nt[++ct]=hd[x], hd[x]=ct, vr[ct]=y, w[ct]=z; }
int d[Mn];
long long dis[Mn];
int T=1, f[21][Mn], ju[21][Mn];
void dfs(int x, int fr) {f[0][x] = fr;
for(int i=hd[x],y; i; i=nt[i]) (y=vr[i])!=fr ? d[y]=d[x]+1, dis[y]=0ll+dis[x]+w[i], dfs(y,x), 0 :0; }
int fid(int x) {int y=x;for(int k=T;k>=0;--k) dis[x]-dis[f[k][y]]<K ?y=f[k][y] :0; return f[0][y]; }
int lca(int x,int y) {
d[x]>d[y] ? x^=y^=x^=y :0;
for(int k=T;k>=0;--k) d[f[k][y]]>=d[x]?y=f[k][y]:0;
if(x==y) return x;
for(int k=T;k>=0;--k) f[k][y]!=f[k][x]? x=f[k][x],y=f[k][y] :0;
return f[0][x];
}
int main() {
scanf("%d%d",&n,&K); for(int i=1,x,y,z; i<n; ++i) {scanf("%d%d%d",&x,&y,&z), ad(x,y,z), ad(y,x,z); }
dfs(d[1]=1,0);
while((1<<T)<n) ++T;
for(int k=1;k<=T;++k)for(int i=1;i<=n;++i) f[k][i] = f[k-1][f[k-1][i]];
for(int i=1;i<=n;++i) ju[0][i] = fid(i);
for(int k=1;k<=T;++k)for(int i=1;i<=n;++i) ju[k][i] = ju[k-1][ju[k-1][i]];
int q;scanf("%d",&q); for(int x,y,z; q; --q) {scanf("%d%d",&x,&y); z=lca(x,y);
int ans = 0;
for(int k=T;k>=0;--k) {
d[ju[k][x]]>=d[z] ? x=ju[k][x], ans+=(1<<k) :0;
d[ju[k][y]]>=d[z] ? y=ju[k][y], ans+=(1<<k) :0;
}
cout << ans+(dis[x]+dis[y]-2*dis[z]>=K) << '
';
}
return 0;}
// 修改后
#include<bits/stdc++.h>
using namespace std;
const int Mn = 2e5+3;
int n,K;
int ct, hd[Mn], nt[Mn*2+1], vr[Mn*2+1], w[Mn*2+1];
void ad(int x, int y, int z)
{nt[++ct]=hd[x], hd[x]=ct, vr[ct]=y, w[ct]=z; }
int d[Mn];
long long dis[Mn];
int T=1, f[21][Mn], ju[21][Mn];
void dfs(int x, int fr)
{f[0][x] = fr;
for(int i=hd[x],y; i; i=nt[i]) (y=vr[i])!=fr ?d[y]=d[x]+1, dis[y]=0ll+dis[x]+w[i], dfs(y,x), 0 :0; }
int fid(int x)
{int y=x;for(int k=T;k>=0;--k) dis[x]-dis[f[k][y]]<K ?y=f[k][y] :0; return f[0][y]; }
int lca(int x,int y)
{
d[x]>d[y] ? x^=y^=x^=y :0;
for(int k=T;k>=0;--k) d[f[k][y]]>=d[x]?y=f[k][y]:0;
if(x==y) return x;
for(int k=T;k>=0;--k) f[k][y]!=f[k][x]? x=f[k][x],y=f[k][y] :0;
return f[0][x];
}
int main()
{
scanf("%d%d",&n,&K);
for(int i=1,x,y,z; i<n; ++i)
{scanf("%d%d%d",&x,&y,&z), ad(x,y,z), ad(y,x,z); }
dfs(d[1]=1,0);
while((1<<T)<n) ++T;
for(int k=1;k<=T;++k)for(int i=1;i<=n;++i) f[k][i]=f[k-1][f[k-1][i]];
for(int i=1;i<=n;++i) ju[0][i] = fid(i);
for(int k=1;k<=T;++k)for(int i=1;i<=n;++i) ju[k][i]=ju[k-1][ju[k-1][i]];
int q; scanf("%d",&q);
for(int x,y,z; q; --q)
{ scanf("%d%d",&x,&y); z=lca(x,y);
int ans = 0;
for(int k=T;k>=0;--k)
{d[ju[k][x]]>=d[z] ? x=ju[k][x], ans+=(1<<k) :0;
d[ju[k][y]]>=d[z] ? y=ju[k][y], ans+=(1<<k) :0; }
cout << ans+(dis[x]+dis[y]-2*dis[z]>=K) << '
';
}
return 0;}
2
// 修改前
#include<bits/stdc++.h>
using namespace std;
const int N=100003, M=300003;
int re()
{int x=0; char c=getchar(); while(!isdigit(c)){c=getchar();}
while(isdigit(c)){x=x*10+c-'0', c=getchar();} return x; }
int n,m;
struct iN{int x,y,s,e; } b[M];
bool cmp2(iN x, iN y) {return x.e>y.e; }
int ct, hd[N], nt[M*2+1], vr[M*2+1], st[M*2+1], ed[M*2+1];
void ad(int x, int y, int s, int e)
{ nt[++ct]=hd[x], hd[x]=ct; vr[ct]=y, st[ct]=s, ed[ct]=e; }
int q;
struct nd{ int id, t; } a[N];
bool cmp1(nd x, nd y) {return x.t<y.t; }
int d1, ans[N];
void dfs(int x, int t)
{ if(x==1)
{ d1 = max(d1,t);
return; }
for(int i=hd[x]; i; i=nt[i]) {
hd[x]=i;
if(t<st[i]) return;
dfs(vr[i],ed[i]);
}
hd[x] = 0;
}
int main() {
n=re(), m=re();
for(int i=1,x,y,s,e;i<=m;++i) b[i].x=re(),b[i].y=re(),b[i].s=re(),b[i].e=re();
sort(b+1,b+1+m,cmp2);
for(int i=1;i<=m;++i) ad(b[i].y,b[i].x,b[i].e,b[i].s);
q=re();
for(int i=1;i<=q;++i) a[i].t=re(), a[i].id=i;
sort(a+1,a+q+1,cmp1);
d1 = -1;
for(int i=1;i<=q;++i) {
dfs(n,a[i].t);
ans[a[i].id] = d1;
}
for(int i=1;i<=q;++i) cout<< ans[i]<< '
';
return 0;
}
//修改后
#include<bits/stdc++.h>
using namespace std;
const int N=100003, M=300003;
int re()
{int x=0; char c=getchar(); while(!isdigit(c))c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar(); return x;
}
int n,m;
struct iN{int x,y,s,e; } b[M];
bool cmp2(iN x, iN y) {return x.e>y.e; }
int q;
struct nd{ int id, t; } a[N];
bool cmp1(nd x, nd y) {return x.t<y.t; }
int ct, hd[N], nt[M*2+1], vr[M*2+1], st[M*2+1], ed[M*2+1];
void ad(int x, int y, int s, int e)
{ nt[++ct]=hd[x], hd[x]=ct; vr[ct]=y, st[ct]=s, ed[ct]=e;
}
int d1, ans[N];
void dfs(int x, int t)
{ if(x==1)
{ d1 = max(d1,t);
return;
}
for(int i=hd[x]; i; i=nt[i])
{ hd[x]=i;
if(t<st[i]) return;
dfs(vr[i],ed[i]);
}
hd[x] = 0;
}
int main() {
n=re(), m=re();
for(int i=1,x,y,s,e;i<=m;++i) b[i].x=re(),b[i].y=re(),b[i].s=re(),b[i].e=re();
sort(b+1,b+1+m,cmp2);
for(int i=1;i<=m;++i) ad(b[i].y,b[i].x,b[i].e,b[i].s);
q=re();
for(int i=1;i<=q;++i) a[i].t=re(), a[i].id=i;
sort(a+1,a+q+1,cmp1);
d1 = -1;
for(int i=1;i<=q;++i)
{ dfs(n,a[i].t);
ans[a[i].id] = d1;
}
for(int i=1;i<=q;++i) cout<< ans[i]<< '
';
return 0;
}