[学习笔记]LCT进阶操作
一般都是维护链的操作。split即可搞定。
进阶操作的话,处理好辅助树和原树的关系即可搞定。
其实,最大的区别就是,splay随便转,辅助树形态变了,但是原树形态不变,makert会让原树形态变化
LCT维护子树信息
真儿子会splay的时候各种变化,但是虚儿子只会在access和link的时候发生变化,其他的时候可以理解为跟着转。
以处理子树sz为例,
处理虚边子树sz,总sz(包括实边)两个
pushup注意下。
access和link注意下。
需要真正找子树信息的时候,考虑把x的后继access掉,把xsplay到根,然后虚边子树的sz就是子树sz了。(前提,makert的根不在x子树里)
模板题:
[BJOI2014]大融合
注意查询x,y的子树大小的话,makert(x),access(y),splay(y).
其实x,y直接连通,所以现在是一个长度为2的链,y是根,x是y的右儿子,然后直接(si[y]+1)*(si[x]+1)即可。(si[x]+1可以换成s[x])
#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=1e5+;
int ch[N][],fa[N],si[N],s[N];
int r[N];
int n,q;
bool nrt(int x){
return (ch[fa[x]][]==x)||(ch[fa[x]][]==x);
}
void pushup(int x){
if(x) s[x]=s[ch[x][]]+s[ch[x][]]+si[x]+;
}
void rev(int x){
swap(ch[x][],ch[x][]);
r[x]^=;
}
void pushdown(int x){
if(r[x]){
rev(ch[x][]);rev(ch[x][]);
r[x]=;
}
}
void rotate(int x){
int y=fa[x],d=ch[fa[x]][]==x;
fa[ch[y][d]=ch[x][!d]]=y;
if(nrt(y)) ch[fa[x]=fa[y]][ch[fa[y]][]==y]=x;
else fa[x]=fa[y];
ch[fa[y]=x][!d]=y;
pushup(y);
}
int sta[N],top;
void splay(int x){
int y=x;
sta[++top]=y;
while(nrt(y)) y=fa[y],sta[++top]=y;
while(top) pushdown(sta[top--]);
int z;
while(nrt(x)){
y=fa[x],z=fa[y];
if(nrt(y)){
rotate(((ch[z][]==y)==(ch[y][]==x))?y:x);
}
rotate(x);
}
pushup(x);
}
void access(int x){
for(int y=;x;y=x,x=fa[x]){
splay(x);
si[x]-=s[y];
si[x]+=s[ch[x][]];
ch[x][]=y;
pushup(x);
}
}
void makert(int x){
access(x);
splay(x);
rev(x);
}
void link(int x,int y){
makert(x);
makert(y);
si[y]+=s[x];
s[y]+=s[x];
fa[x]=y;
pushup(y);
}
int query(int x,int y){
makert(x);access(y);
return (long long)(si[x]+)*(si[y]+);
}
int main(){
rd(n);rd(q);
char cc[];
int x,y;
for(reg i=;i<=n;++i){
si[i]=;s[i]=;
}
while(q--){
scanf("%s",cc+);
rd(x);rd(y);
if(cc[]=='A'){
link(x,y);
}else{
printf("%d\n",query(x,y));
}
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/18 11:13:18
*/
大融合
LCT维护联通块信息(边双联通分量)
每个LCT的点,是一个边双。只不过存在一些名存实亡的点。
只能支持插入边,维护这个边双连通分量缩点之后得到的树
外面要再用一个并查集维护每个点所在的边双的代表节点。即并查集树的树根。
(这里又多了一个并查集树,可以理解为,就是为了缩点打的懒标记而已(否则暴力缩点岂不是O(n)的?))
(upda:2019.2.14:更好的解释是,其实我们扫右儿子的子树的时候,已经完成了缩点,但是右儿子的虚儿子没有记录,不能直接指向x,所以只能“懒惰”用并查集先记录一下了)
合并缩环的时候,类似于打标记,把这个实链的点的father暴力指向x,然后干掉x的右儿子,这些部分就不存在了。
名存实亡。都用x代替了。
然后pushup(x)
但是,可能这些实链的子树,还必须要继承到x上,怎么办呢?
由于类似于打标记,先不继承它,
因为每次处理对于链或者连通性的询问都要access,所以在这个上面做文章。
access的时候,跳father用并查集直接跳到边双的代表点p。然后顺便把自己的辅助树的father设为p。
这样,就会把子树继承上去了,并且真正意义上实现了缩点,
使得边双之间用桥连接。
由于有并查集,所以每次都要x=fin(x)找到真正的点再处理。
看似复杂,其实理解上,就是多了一些个用并查集维护的懒标记,用到的时候及时还原即可。
(但是对于维护边双联通分量,还要维护缩完点后的树的子树信息的话,,,,好像子树不能及时继承上去,估计就比较难办了。。2333)
(upda:2019.2.14:上面那个说的不对,子树信息当然可以做,因为缩点对于最高点的x的子树信息没有影响的。)
(upda:2019.3.13:emm,要看维护什么子树信息了。sz的话是不虚的,但是具体距离什么的还是没法办)
例题1:[AHOI2005]航线规划——LCT维护边双联通分量
例题2:【bzoj2959】长跑
维护的sz变成sz[x]=sz[ls]+sz[rs]+my[x]
my[x]是自己边双内部的刷卡机个数
对于2操作,找到真正的边双点,my[root]+=new-old[x],old[x]=new;
操作3直接查询链上的sz即可。
#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
#define ls t[x].ch[0]
#define rs t[x].ch[1]
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=+;
int n,m;
struct node{
int sz,fa,ch[],r;
int my;
}t[N];
int fa[N];
int fin(int x){
return fa[x]==x?x:fa[x]=fin(fa[x]);
}
bool nrt(int x){
return (t[t[x].fa].ch[]==x)||(t[t[x].fa].ch[]==x);
}
void rev(int x){
swap(t[x].ch[],t[x].ch[]);
t[x].r^=;
}
void pushdown(int x){
if(t[x].r){
t[x].r=;
rev(ls);rev(rs);
}
}
void pushup(int x){
if(x) t[x].sz=t[ls].sz+t[rs].sz+t[x].my;
}
void rotate(int x){
int y=t[x].fa,d=t[y].ch[]==x;
t[t[y].ch[d]=t[x].ch[!d]].fa=y;
if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[]==y]=x;
else t[x].fa=t[y].fa;
t[t[y].fa=x].ch[!d]=y;
pushup(y);
}
int sta[N];
void splay(int x){
int y=x,z=;
sta[++z]=y;
while(nrt(y)) y=t[y].fa,sta[++z]=y;
while(z) pushdown(sta[z--]); while(nrt(x)){
y=t[x].fa,z=t[y].fa;
if(nrt(y)){
rotate(((t[y].ch[]==x)==(t[z].ch[]==y))?y:x);
}
rotate(x);
}
pushup(x);
}
void access(int x){
for(reg y=;x;y=x,x=t[y].fa=fin(t[x].fa)){
splay(x);rs=y;pushup(x);
}
}
void makert(int x){
access(x);splay(x);rev(x);
}
int findrt(int x){
access(x);splay(x);
pushdown(x);
while(t[x].ch[]) pushdown(x=t[x].ch[]);
splay(x);
return x;
}
void dele(int x,int y){
if(x) fa[x]=y,t[y].my+=t[x].my,dele(ls,y),dele(rs,y);
}
void merge(int x,int y){
if(x==y) return;
makert(x);
if(findrt(y)!=x){
t[x].fa=y;
pushup(y);
return;
}
dele(t[x].ch[],x);
t[x].ch[]=;
pushup(x);
}
void split(int x,int y){
makert(x);access(y);splay(y);
}
int query(int x,int y){
makert(x);
if(findrt(y)!=x) return -;
splay(y);
return t[y].sz;
}
int now[N];
int main(){
rd(n);rd(m);
int x,y;
for(reg i=;i<=n;++i){
rd(x);
now[i]=x;
fa[i]=i;t[i].sz=x;t[i].my=x;
}
int c;
for(reg i=;i<=m;++i){
rd(c);rd(x);rd(y);
if(c==){
x=fin(x);y=fin(y);
merge(x,y);
}else if(c==){
int tmp=y-now[x];
//cout<<" tmp "<<tmp<<endl;
now[x]=y;
x=fin(x);
//cout<<" xx "<<x<<endl;
//splay(x);
makert(x);
t[x].my+=tmp;
pushup(x);
}else{
printf("%d\n",query(fin(x),fin(y)));
}
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/19 9:57:28
*/
长跑
LCT维护边权(常用生成树)
边,直接变成点,因为LCT不能直接维护边。
生成树边的信息记录在点上。
水管局长(动态最小生成树)
严格次小生成树(也可以不用LCT)
最小差值生成树:
肯定要把边排序,枚举固定一个较大值,
暴力的做法是不断把小的加进去,直到成为一个联通块。
考虑是否能用到上一次处理的信息,
不断加入值的时候,如果成环,那么把环上最小值替换掉即可。
这样,通过r-1的最小差值生成树,删除并添加一条边,就可以得到r的最小差值生成树
正确性的话,
如果存在一个更靠后的L使得[L,R]是生成树,那么必然是可以用R之前的边把一些小的边替换掉,之前肯定已经处理这种情况了。
代码:
注意:
1.pushup更新值的时候,不严格优秀就可以更新,不能只取<,否则在相等的时候会错误。
2.处理x,y的链的时候,时刻注意谁在上面,access(y)可能y就变到了x的祖先。以及findrt(y)也可能会。
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
#define ls t[x].ch[0]
#define rs t[x].ch[1]
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=+;
const int M=+;
const int inf=0x3f3f3f3f;
int n,m;
int tot;
int ptr;
struct node{
int ch[],fa,r;
int mi,id;
int val;
int from;
}t[N+M];
bool nrt(int x){
return (t[t[x].fa].ch[]==x)||(t[t[x].fa].ch[]==x);
}
void rev(int x){
swap(t[x].ch[],t[x].ch[]);
t[x].r^=;
}
void pushup(int x){
if(t[x].val<=t[ls].mi&&t[x].val<=t[rs].mi){
t[x].mi=t[x].val;
t[x].id=x;
}
else if(t[ls].mi<=t[x].val&&t[ls].mi<=t[rs].mi){
t[x].mi=t[ls].mi;
t[x].id=t[ls].id;
}
else{
t[x].mi=t[rs].mi;
t[x].id=t[rs].id;
}
}
void pushdown(int x){
if(t[x].r){
rev(t[x].ch[]),rev(t[x].ch[]);
t[x].r=;
}
}
void rotate(int x){
int y=t[x].fa,d=t[y].ch[]==x;
t[t[y].ch[d]=t[x].ch[!d]].fa=y;
if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[]==y]=x;
else t[x].fa=t[y].fa;
t[t[x].ch[!d]=y].fa=x;
pushup(y);
}
int sta[N];
void splay(int x){
int y=x,z=;
sta[++z]=y;
while(nrt(y)) y=t[y].fa,sta[++z]=y;
while(z) pushdown(sta[z--]); while(nrt(x)){
y=t[x].fa,z=t[y].fa;
if(nrt(y)){
rotate(((t[z].ch[]==y)==(t[y].ch[]==x))?y:x);
}
rotate(x);
}
pushup(x);
}
void access(int x){
for(reg y=;x;y=x,x=t[x].fa){
splay(x);
t[x].ch[]=y;
pushup(x);
}
}
void makert(int x){
//cout<<" making "<<x<<" "<<t[x].fa<<endl;
access(x);
//cout<<" access end "<<endl;
splay(x);
//cout<<" splay end "<<endl;
rev(x);
}
int findrt(int x){
access(x);splay(x);
while(t[x].ch[]) x=t[x].ch[];
splay(x);
return x;
}
int c=;
bool in[M];
void link(int x,int y,int z,int fr){
// cout<<" link "<<x<<" "<<y<<" "<<z<<" "<<fr<<" "<<tot<<endl;
t[tot].val=z;t[tot].id=tot,t[tot].mi=z;t[tot].from=fr;
// cout<<" t[4] "<<t[4].mi<<" "<<t[4].id<<endl;
in[fr]=;
makert(x);
// cout<<" sdfsdfj "<<endl;
// cout<<findrt(y)<<endl;
// cout<<" over "<<endl;
if(findrt(y)!=x){
// cout<<" add new "<<endl;
t[x].fa=tot;
t[tot].fa=y;
// pushup(tot);
// pushup(y);
++c;
return;
}
pushup(x);
// cout<<t[x].mi<<" "<<t[x].val<<" "<<ls<<" "<<rs<<" "<<t[4].mi<<" "<<t[4].id<<endl;
int lp=t[x].id;
// cout<<" kil "<<lp<<" "<<t[lp].from<<" "<<t[lp].val<<endl;
in[t[lp].from]=;
splay(lp);
t[t[lp].ch[]].fa=;
t[t[lp].ch[]].fa=; makert(x);
t[x].fa=tot;
t[tot].fa=y;
}
struct edge{
int x,y,z;
bool friend operator <(edge a,edge b){
return a.z<b.z;
}
}e[M];
int main(){
rd(n);rd(m);
int x,y,z;
for(reg i=;i<=m;++i){
rd(x);rd(y);rd(z);
e[i].x=x;e[i].y=y;e[i].z=z;
}
sort(e+,e+m+);
tot=n;
int ans=0x3f3f3f3f;
t[].val=inf,t[].mi=inf,t[].id=-;
for(reg i=;i<=n;++i){
t[i].val=inf;t[i].mi=inf;t[i].id=-;
}
for(reg i=;i<=m;++i){
// cout<<" iiii "<<i<<"---------------------------"<<" "<<e[i].z<<endl;
++tot;
if(e[i].x!=e[i].y) link(e[i].x,e[i].y,e[i].z,i);
while(in[ptr]==) ++ptr;
if(c==n-){
// cout<<" ok "<<e[i].z<<" "<<e[ptr].z<<endl;
// cout<<" ptr "<<ptr<<endl;
ans=min(ans,e[i].z-e[ptr].z);
}
}
printf("%d",ans);
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/19 8:17:20
*/
最小差值生成树
LCT维护树上染色联通块
[SDOI2017]树点涂色
到根路径的染色好似access操作,而且每种颜色都是新出现的,并且每一种颜色的地位相同。
用LCT维护颜色块的集合,只用到access操作,再用一个线段树维护dfs序,num[x]表示x点到根节点的路径颜色数目。
只有在虚边变成实边的时候,才会发生真正意义上的颜色改变,会对子树答案造成影响,
具体来说,变换重儿子的时候,把原来的位置的子树的每个num加上1,新儿子的num每个减掉1
操作2,num[a]+num[b]-2*num[lca]+1(分类讨论一下即可证明)
操作3,区间求max
这个题,LCT不算是用来维护动态树的工具,只是因为access和操作1非常相似,从而进行了一个“建模”,用LCT来拟合这个操作。
#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=1e5+;
const int inf=0x3f3f3f3f;
int mx[*N],ad[*N];
int n,m;
struct edge{
int nxt,to;
}e[*N];
struct node{
int fa,ch[];
}t[N];
int hd[N],cnt;
void add(int x,int y){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
int dfn[N],dfn2[N],df;
int fdfn[N],dep[N];
int fa[N][];
void dfs(int x,int d){
dfn[x]=++df;
fdfn[df]=x;
dep[x]=d;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa[x][]) continue;
t[y].fa=x;
fa[y][]=x;
dfs(y,d+);
}
dfn2[x]=df;
}
void pushup(int x){
mx[x]=max(mx[x<<],mx[x<<|]);
}
void pushdown(int x){
if(!ad[x]) return;
ad[x<<]+=ad[x];
ad[x<<|]+=ad[x];
mx[x<<]+=ad[x];
mx[x<<|]+=ad[x];
ad[x]=;
}
void build(int x,int l,int r){
if(l==r){
mx[x]=dep[fdfn[l]];return;
}
build(x<<,l,mid);build(x<<|,mid+,r);
pushup(x);
}
void upda(int x,int l,int r,int L,int R,int c){
if(L<=l&&r<=R){
ad[x]+=c;mx[x]+=c;return;
}
pushdown(x);
if(L<=mid) upda(x<<,l,mid,L,R,c);
if(mid<R) upda(x<<|,mid+,r,L,R,c);
pushup(x);
}
int query(int x,int l,int r,int p){
if(l==r){
return mx[x];
}
pushdown(x);
if(p<=mid) return query(x<<,l,mid,p);
return query(x<<|,mid+,r,p);
}
int ask(int x,int l,int r,int L,int R){
if(L<=l&&r<=R){
return mx[x];
}
pushdown(x);
int ret=;
if(L<=mid) ret=max(ret,ask(x<<,l,mid,L,R));
if(mid<R) ret=max(ret,ask(x<<|,mid+,r,L,R));
return ret;
} bool nrt(int x){
return t[t[x].fa].ch[]==x||t[t[x].fa].ch[]==x;
}
void rotate(int x){
int y=t[x].fa,d=t[y].ch[]==x;
t[t[y].ch[d]=t[x].ch[!d]].fa=y;
if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[]==y]=x;
else t[x].fa=t[y].fa;
t[t[x].ch[!d]=y].fa=x;
}
void splay(int x){
while(nrt(x)){
int y=t[x].fa,z=t[y].fa;
if(nrt(y)){
rotate(((t[z].ch[]==y)==(t[y].ch[]==x))?y:x);
}
rotate(x);
}
}
int bac(int x){
if(t[x].ch[]==) return ;
x=t[x].ch[];
while(t[x].ch[]) x=t[x].ch[];
return x;
}
int pre(int x){
while(t[x].ch[]) x=t[x].ch[];
return x;
}
void access(int x){
//cout<<" accessing "<<x<<endl;
for(reg y=;x;y=x,x=t[x].fa){
//cout<<" x y "<<x<<" "<<y<<endl;
splay(x);
int lp=bac(x);
//cout<<" bac "<<lp<<endl;
if(lp){
upda(,,n,dfn[lp],dfn2[lp],);
}
if(y){
lp=pre(y);
// cout<<" pre "<<lp<<endl;
upda(,,n,dfn[lp],dfn2[lp],-);
}
t[x].ch[]=y;
}
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(reg j=;j>=;--j){
if(dep[fa[x][j]]>=dep[y]){
x=fa[x][j];
}
}
if(x==y) return x;
for(reg j=;j>=;--j){
if(fa[x][j]!=fa[y][j]){
x=fa[x][j];y=fa[y][j];
}
}
return fa[x][];
}
int main(){
rd(n);rd(m);
int x,y;
for(reg i=;i<n;++i){
rd(x);rd(y);
add(x,y);add(y,x);
}
dfs(,);
dep[]=-;
for(reg j=;j<=;++j){
for(reg i=;i<=n;++i){
fa[i][j]=fa[fa[i][j-]][j-];
}
}
// for(reg i=1;i<=n;++i){
// cout<<i<<" "<<dfn[i]<<" "<<fdfn[i]<<" "<<dep[i]<<endl;
// }
build(,,n);
int c;
while(m--){
rd(c);
if(c==){
rd(x);
access(x);
}
else if(c==){
rd(x);rd(y);
int anc=lca(x,y);
// cout<<" anc "<<anc<<endl;
//cout<<" ---- "<<query(1,1,n,dfn[x])<<" "<<query(1,1,n,dfn[y])<<" "<<query(1,1,n,dfn[anc])<<endl;
printf("%d\n",query(,,n,dfn[x])+query(,,n,dfn[y])-*query(,,n,dfn[anc])+);
}else{
rd(x);
printf("%d\n",ask(,,n,dfn[x],dfn2[x]));
}
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/19 20:08:02
*/
树点涂色
重组病毒、LCT+SAM查询区间子串问题都是这个思路
[学习笔记]LCT进阶操作的更多相关文章
- IOS学习笔记25—HTTP操作之ASIHTTPRequest
IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...
- java学习笔记07--日期操作类
java学习笔记07--日期操作类 一.Date类 在java.util包中定义了Date类,Date类本身使用非常简单,直接输出其实例化对象即可. public class T { public ...
- Django学习笔记(进阶篇)
Django学习笔记(进阶篇):http://www.cnblogs.com/wupeiqi/articles/5246483.html
- jQuery学习笔记之DOM操作、事件绑定(2)
jQuery学习笔记之DOM操作.事件绑定(2) --------------------学习目录------------------------ 4.DOM操作 5.事件绑定 源码地址: https ...
- tensorflow学习笔记——使用TensorFlow操作MNIST数据(2)
tensorflow学习笔记——使用TensorFlow操作MNIST数据(1) 一:神经网络知识点整理 1.1,多层:使用多层权重,例如多层全连接方式 以下定义了三个隐藏层的全连接方式的神经网络样例 ...
- tensorflow学习笔记——使用TensorFlow操作MNIST数据(1)
续集请点击我:tensorflow学习笔记——使用TensorFlow操作MNIST数据(2) 本节开始学习使用tensorflow教程,当然从最简单的MNIST开始.这怎么说呢,就好比编程入门有He ...
- ROS学习笔记INF-重要操作列表
该笔记将重要操作的步骤进行列表,以便查询: 添加消息 在包中的msg文件夹中创建msg文件 确保package.xml中的如下代码段被启用: <build_depend>message_g ...
- Java WebService学习笔记 - Axis进阶(二)
上一篇 Java WebService学习笔记 - Axis(一) 前一篇博文中简单介绍了Axis的使用方法,这篇将介绍一些Axis的一些高级特性 Axis中Handler的使用 Handler ...
- Oracle 学习笔记 14 -- 集合操作和高级子查询
Oracel提供了三种类型的集合操作:各自是并(UNION) .交(INTERSECT). 差(MINUS) UNION :将多个操作的结果合并到一个查询结果中,返回查询结果的并集,自己主动去掉反复的 ...
随机推荐
- Bad escape character ‘ygen’ 错误原因!
ssh-keygen -t rsa -C “邮箱” ssh-keygen 命令中间没有空格,如果在ssh后面加上空格,会得到Bad escape character ‘ygen’.的错误.
- 文件夹选项-安装功能-window服务
我们初次使用windows10在显示一个文件的时候,可能不会将文件的扩展名显示出来,但是我们很多地方又需要更改文件的扩展名,打开文件的扩展名有两种方式 打开此电脑 ->>>点击右上方 ...
- (数据科学学习手札01)Python与R基本数据结构之异同
Python 1.列表(list) list1 = [i for i in range(10)] list1[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 特点:可遍历,可索引,可切片 ...
- Java——Random类随机整数---18.10.11
一.Random类的定义 1.Random类位于java.util包中,主要用于生成 伪随机数 2.random类将 种子数 作为随机算法的起源数字,计算生成伪随机数,其与生成的随机数字的区间无关 3 ...
- 详解 RPL、DPL、CPL 的关系
保护模式中最重要的一个思想就是通过分级把代码隔离了起来,不同的代码在不同的级别,使大多数情况下都只和同级代码发生关系.Intel的80286以上的cpu可以识別4个特权级(或特权层) ,0级到3级.数 ...
- Hue 工具使用
Hue 是一个 Web 接口的 Hadoop 分析数据工具,由 Cloudra 公司开源 官方网址 Github 地址 -> 安装方法 文档地址 一.Build 1.ubuntu安装所需环境(以 ...
- python下的自动化测试--selenium 验证码输入问题
之前一直在研究scrapy下数据抓取,在研究ajax数据抓取时碰巧研究了一下selenium,确实很实用,不过只做scrapy下的数据抓取,不怎么合适,一是性能的损耗,一直需要开一个浏览器,二是对于爬 ...
- 快速平方根算法的javascript实现
前几天看见了一个来自雷神之槌的平方根源码,原理多方有介绍,不赘述. 源码是c语言写的,我思考后发现这样的算法在javascript中也是可以完成的. function InvSqrt(x){ var ...
- C++学习003-#define 自定义宏
C++中可以用#define来定义自定义的宏 也可以用使用#define来定义常量 但是#define只是简单的替换,在定义常量的时候没有语法检测 所以在C++定义常量可以使用 Const修饰 #d ...
- 【java并发编程实战】第六章:线程池
1.线程池 众所周知创建大量线程时代价是非常大的: - 线程的生命周期开销非常大:创建需要时间,导致延迟处理请求,jvm需要分配空间. - 资源消耗:线程需要占用空间,如果线程数大于可用的处理器数量, ...