首页 > 其他分享 >平衡树练习总结

平衡树练习总结

时间:2024-11-14 21:46:42浏览次数:1  
标签:总结 return val rs int 练习 tree ls 平衡

P6136 【模板】普通平衡树(数据加强版)

狠狠地被有旋 Treap 恶心了一把,从此再也不写有旋 Treap!

还是 FHQ Treap 爽,比有旋 Treap 短一半。

有旋 Treap

结构体及相关数据定义

const int INF=1e18;
struct Treap{
	int ls,rs;
	int val,dat;
	int cnt,sz;
}tree[M+N];
#define ls(p) tree[p].ls
#define rs(p) tree[p].rs
int root,idx;

建立新点,返回新点编号

mt19937 engine(chrono::steady_clock::now().time_since_epoch().count());
inline int create(int val)
{
	tree[++idx]={0,0,val,(int)engine(),1,1};
	return idx;
}

更新节点 \(p\) 的大小

inline void update(int p)
{
	tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+tree[p].cnt;
	return;
}

右旋(zig)左旋(zag)。

注意函数和左右的对应关系!先右再左!(谁发明的反人类命名)

inline void zig(int &p) //right rotation 
{
	int q=ls(p);
	tree[p].ls=rs(q);
	tree[q].rs=p;
	p=q;
	update(rs(p)),update(p);
	return;
}
inline void zag(int &p) //left rotation
{
	int q=rs(p);
	tree[p].rs=ls(q);
	tree[q].ls=p;
	p=q;
	update(ls(p)),update(p);
	return;
}

建树,添加 \(-\infty\) 和 \(+\infty\) 两个点,其中 \(-\infty\) 作为父节点,\(+\infty\) 作为右子节点。

据说直接建会导致两点的 \(dat\) 不一定满足堆的关系,所以标有 FLAG 的地方调整了一下 \(dat\) 的大小关系。不过没有这一行也能过,因为第一次向根右边加点的时候就会自动把关系调对。

其实这些没什么必要关注,因为 \(dat\) 只是为了维持 Treap 的平衡而存在的,有那么几个点乱了影响不大。

inline void Build()
{
	root=create(-INF);
	tree[root].rs=create(INF);
	tree[rs(root)].dat=tree[root].dat-1; //FLAG
	update(root);
	return;
}

根据值获取排名,没什么需要注意的。

此处和下面标有 error 的行在合法输入下理论上不会进入。

int get_rank(int val,int p)
{
	if(!p) return 1;
	if(val==tree[p].val) return tree[ls(p)].sz+1;
	if(val<tree[p].val) return get_rank(val,ls(p));
	if(val>tree[p].val) return get_rank(val,rs(p))+tree[ls(p)].sz+tree[p].cnt;
	return -INF; //error
}

根据排名获取值,同样没有什么需要注意的。

int get_value(int rank,int p)
{
	if(!p) return INF; //error
	if(rank<=tree[ls(p)].sz) return get_value(rank,ls(p));
	else if(rank<=tree[ls(p)].sz+tree[p].cnt) return tree[p].val;
	else return get_value(rank-tree[ls(p)].sz-tree[p].cnt,rs(p));
}

插入节点,需要注意旋转的方向,最好手动模拟一下。

右旋(sig)是把左子节点拉上来,左旋(zag)是把右子节点拉上来。

void Insert(int val,int &p)
{
	if(!p) {p=create(val); return;}
	if(val==tree[p].val)
	{
		tree[p].cnt++;
		update(p);
		return;
	}
	if(val<tree[p].val)
	{
		Insert(val,ls(p));
		if(tree[p].dat<tree[ls(p)].dat) zig(p);
	}
	if(val>tree[p].val)
	{
		Insert(val,rs(p));
		if(tree[p].dat<tree[rs(p)].dat) zag(p);
	}
	update(p);
	return;
}

删点,原理是把当前节点转到叶子上去删,注意此时需要保证 \(dat\) 之间的关系仍然正确,即 \(dat\) 大的做新的父节点。

void Remove(int val,int &p)
{
	if(!p) return;
	if(val==tree[p].val)
	{
		if(tree[p].cnt>1)
		{
			tree[p].cnt--;
			update(p);
			return;
		}
		else if(ls(p)||rs(p))
		{
			if(!rs(p) || tree[ls(p)].dat>tree[rs(p)].dat)
				zig(p), Remove(val,rs(p));
			else zag(p), Remove(val,ls(p));
			update(p);
		}
		else p=0;
		return;
	}
	if(val<tree[p].val) Remove(val,ls(p));
	if(val>tree[p].val) Remove(val,rs(p));
	update(p);
	return;
}

找前驱,重头戏来了,就是这个函数害我多调 \(\infty\) 小时。

在有标记的一行,我原本是这样写的:

if(val<tree[p].val) p=ls(p);
if(val>tree[p].val) p=rs(p);

一眼看过去,似乎没问题是吧。但是!第一行修改完后的新 \(p\) 在第二行可能再次判断成功,又被更新一次。所以我成功地 WA 了 \(30+\) 发。

改成这样:

if(val<tree[p].val) p=ls(p);
else p=rs(p);

或下面的三目运算符就没问题了。

int get_prev(int val)
{
	int res=0,p=root;
	while(p)
	{
		if(val==tree[p].val)
		{
			if(ls(p)>0)
			{
				p=ls(p);
				while(rs(p)>0) p=rs(p);
				res=p;
			}
			break;
		}
		if(tree[p].val<val && (tree[p].val>tree[res].val || !res)) res=p;
		p=val<tree[p].val?ls(p):rs(p); //WTF!!!!!!!!!!!!!!!!!!
	}
	return tree[res].val;
}

找后继,这里的注意事项同上。

int get_next(int val)
{
	int res=0,p=root;
	while(p)
	{
		if(val==tree[p].val)
		{
			if(rs(p))
			{
				p=rs(p);
				while(ls(p)) p=ls(p);
				res=p;
			}
			break;
		}
		if(tree[p].val>val && (tree[p].val<tree[res].val || !res)) res=p;
		p=val<tree[p].val?ls(p):rs(p);
	}
	return tree[res].val;
}

这告诉我们,在代码中需要时刻关注变量的变化,多个 if 或是带引用的函数等都会改变变量的值,这时候就要留心新值是不是我们所需要的

另外还有,少用默认函数参数(int haha(int x=0) 这种),这样写一旦代码中不小心漏了参数,编译器不会报错,浪费许多时间差错


完整代码:

点击查看代码
#include<cstdio>
#include<random>
#include<chrono>
#define int long long
using namespace std;

namespace IO{
template<typename TYPE> void read(TYPE &x)
{
	x=0; bool neg=false; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')neg=true;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+(ch^'0');ch=getchar();}
	if(neg){x=-x;} return;
}
template<typename TYPE> void write(TYPE x)
{
	if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;}
	static int sta[55];int statop=0; while(x){sta[++statop]=x%10;x/=10;}
	while(statop){putchar('0'+sta[statop--]);} return;
}
template<typename TYPE> void write(TYPE x,char ch){write(x);putchar(ch);return;}
} using namespace IO;

const int N=1e6+5,M=3e6+5;
int n,m,a[N];

namespace TREAP{

const int INF=1e18;
struct Treap{
	int ls,rs;
	int val,dat;
	int cnt,sz;
}tree[M+N];
#define ls(p) tree[p].ls
#define rs(p) tree[p].rs
int root,idx;

mt19937 engine(chrono::steady_clock::now().time_since_epoch().count());
inline int create(int val)
{
	tree[++idx]={0,0,val,(int)engine(),1,1};
	return idx;
}
inline void update(int p)
{
	tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+tree[p].cnt;
	return;
}
inline void zig(int &p) //right rotation 
{
	int q=ls(p);
	tree[p].ls=rs(q);
	tree[q].rs=p;
	p=q;
	update(rs(p)),update(p);
	return;
}
inline void zag(int &p) //left rotation
{
	int q=rs(p);
	tree[p].rs=ls(q);
	tree[q].ls=p;
	p=q;
	update(ls(p)),update(p);
	return;
}

inline void Build()
{
	root=create(-INF);
	tree[root].rs=create(INF);
	tree[rs(root)].dat=tree[root].dat-1;
	update(root);
	return;
}

int get_rank(int val,int p)
{
	if(!p) return 1;
	if(val==tree[p].val) return tree[ls(p)].sz+1;
	if(val<tree[p].val) return get_rank(val,ls(p));
	if(val>tree[p].val) return get_rank(val,rs(p))+tree[ls(p)].sz+tree[p].cnt;
	return -INF; //error
}
int get_value(int rank,int p)
{
	if(!p) return INF; //error
	if(rank<=tree[ls(p)].sz) return get_value(rank,ls(p));
	else if(rank<=tree[ls(p)].sz+tree[p].cnt) return tree[p].val;
	else return get_value(rank-tree[ls(p)].sz-tree[p].cnt,rs(p));
}

void Insert(int val,int &p)
{
	if(!p) {p=create(val); return;}
	if(val==tree[p].val)
	{
		tree[p].cnt++;
		update(p);
		return;
	}
	if(val<tree[p].val)
	{
		Insert(val,ls(p));
		if(tree[p].dat<tree[ls(p)].dat) zig(p);
	}
	if(val>tree[p].val)
	{
		Insert(val,rs(p));
		if(tree[p].dat<tree[rs(p)].dat) zag(p);
	}
	update(p);
	return;
}
void Remove(int val,int &p)
{
	if(!p) return;
	if(val==tree[p].val)
	{
		if(tree[p].cnt>1)
		{
			tree[p].cnt--;
			update(p);
			return;
		}
		else if(ls(p)||rs(p))
		{
			if(!rs(p) || tree[ls(p)].dat>tree[rs(p)].dat)
				zig(p), Remove(val,rs(p));
			else zag(p), Remove(val,ls(p));
			update(p);
		}
		else p=0;
		return;
	}
	if(val<tree[p].val) Remove(val,ls(p));
	if(val>tree[p].val) Remove(val,rs(p));
	update(p);
	return;
}

int get_prev(int val)
{
	int res=0,p=root;
	while(p)
	{
		if(val==tree[p].val)
		{
			if(ls(p)>0)
			{
				p=ls(p);
				while(rs(p)>0) p=rs(p);
				res=p;
			}
			break;
		}
		if(tree[p].val<val && (tree[p].val>tree[res].val || !res)) res=p;
		p=val<tree[p].val?ls(p):rs(p); //WTF!!!!!!!!!!!!!!!!!!
	}
	return tree[res].val;
}
int get_next(int val)
{
	int res=0,p=root;
	while(p)
	{
		if(val==tree[p].val)
		{
			if(rs(p))
			{
				p=rs(p);
				while(ls(p)) p=ls(p);
				res=p;
			}
			break;
		}
		if(tree[p].val>val && (tree[p].val<tree[res].val || !res)) res=p;
		p=val<tree[p].val?ls(p):rs(p);
	}
	return tree[res].val;
}

}

signed main()
{
	read(n),read(m);
	TREAP::Build();
	for(int i=1;i<=n;i++)
	{
		read(a[i]);
		TREAP::Insert(a[i],TREAP::root);
	}
	int ans=0,last=0;
	int tot=n;
	for(int i=1;i<=m;i++)
	{
		int op,x; read(op),read(x);
		x^=last;
		switch(op)
		{
			case 1:
				TREAP::Insert(x,TREAP::root);
				tot++;
				break;
			case 2:
				TREAP::Remove(x,TREAP::root);
				tot--;
				break;
			case 3:
				last=TREAP::get_rank(x,TREAP::root)-1;
				ans^=last;
				break;
			case 4:
				last=TREAP::get_value(x+1,TREAP::root);
				ans^=last;
				break;
			case 5:
				last=TREAP::get_prev(x);
				ans^=last;
				break;
			case 6:
				last=TREAP::get_next(x);
				ans^=last;
				break;
			default:
				break;
		}
	}
	write(ans,'\n');
	return 0;
}

无旋 Treap(FHQ Treap)

相关变量及结构体定义。

struct Treap{
	int ls,rs;
	int val,dat;
	int sz;
}tree[N+M];
int idx,root;
#define ls(p) tree[p].ls
#define rs(p) tree[p].rs

新建点,注意 FHQ Treap 不会记录某个值出现的次数,而是每一个都新建一个点。

mt19937 engine(chrono::steady_clock::now().time_since_epoch().count());
inline int create(int val)
{
	tree[++idx]={0,0,val,(int)engine(),1};
	return idx;
}

更新点 \(p\) 子树大小。

inline void update(int p)
{
	tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+1;
	return;
}

分割函数。

引用的 \(L\)、\(R\) 相当于是预留的一个位置,要求处理过后把两棵子树的根放在这个空位里面

void Split(int val,int p,int &L,int &R)
{
	if(!p) {L=R=0; return;}
	if(tree[p].val<=val)
	{
		L=p;
		Split(val,rs(p),rs(p),R);
		update(L);
	}
	else
	{
		R=p;
		Split(val,ls(p),L,ls(p));
		update(R);
	}
	return;
}

合并两棵树,返回根节点。

注意此时要求 \(dat\) 满足堆性质,所以 需要把 \(dat\) 较大的作为根节点。

int Merge(int L,int R)
{
	if(!L||!R) return L|R;
	if(tree[L].dat>tree[R].dat)
	{
		rs(L)=Merge(rs(L),R);
		update(L);
		return L;
	}
	else
	{
		ls(R)=Merge(L,ls(R));
		update(R);
		return R;
	}
}

插入节点,其实就是找到位置以后放进去。

void Insert(int val)
{
	int p=create(val);
	int L,R; Split(val,root,L,R);
	root=Merge(L,Merge(p,R));
	return;
}

删除节点。

直接分割出来的是一棵子树,里面全部都是所求值。因为只用删除一个,所以只删根节点,其它的全部合并起来就可以了。

void Remove(int val)
{
	int NR,R; Split(val,root,NR,R);
	int L,MID; Split(val-1,NR,L,MID);
	MID=Merge(ls(MID),rs(MID));
	root=Merge(L,Merge(MID,R));
	return;
}

根据值获取排名。这里获取到的一定是第一个该值的排名

int get_rank(int val)
{
	int L,R; Split(val-1,root,L,R);
	int res=tree[L].sz+1;
	root=Merge(L,R);
	return res;
}

根据排名获取值,这次不能用分裂合并来取巧了。

int get_value(int rank)
{
	int p=root;
	while(p)
	{
		int lsz=tree[ls(p)].sz;
		if(rank==lsz+1) return tree[p].val;
		if(rank<=lsz) p=ls(p);
		else rank-=lsz+1,p=rs(p);
	}
	return -1;
}

逆天超短代码。

找前驱直接找排名比它第一位的即可(找某个值的排名一定是第一个该值的排名,所以减一以后就是前驱)。

int get_prev(int val)
{
	return get_value(get_rank(val)-1);
}

找后继不能再用排名,但是由于 get_rank 的特性,其结果更像是 lower_bound,所以找所求值加一对应排名对应值即可。

int get_next(int val)
{
	return get_value(get_rank(val+1));
}

完整代码(就喜欢短的)

点击查看代码
#include<cstdio>
#include<random>
#include<chrono>
using namespace std;

namespace IO{
template<typename TYPE> void read(TYPE &x)
{
	x=0; bool neg=false; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')neg=true;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+(ch^'0');ch=getchar();}
	if(neg){x=-x;} return;
}
template<typename TYPE> void write(TYPE x)
{
	if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;}
	static int sta[55];int statop=0; while(x){sta[++statop]=x%10;x/=10;}
	while(statop){putchar('0'+sta[statop--]);} return;
}
template<typename TYPE> void write(TYPE x,char ch){write(x);putchar(ch);return;}
} using namespace IO;

const int N=1e5+5,M=1e6+5;
int n,m,a[N];

namespace FHQ{

struct Treap{
	int ls,rs;
	int val,dat;
	int sz;
}tree[N+M];
int idx,root;
#define ls(p) tree[p].ls
#define rs(p) tree[p].rs

mt19937 engine(chrono::steady_clock::now().time_since_epoch().count());
inline int create(int val)
{
	tree[++idx]={0,0,val,(int)engine(),1};
	return idx;
}
inline void update(int p)
{
	tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+1;
	return;
}

void Split(int val,int p,int &L,int &R) //L,R¿ÉÀí½âΪÏóÕ÷Ò»¸öλÖà 
{
	if(!p) {L=R=0; return;}
	if(tree[p].val<=val)
	{
		L=p;
		Split(val,rs(p),rs(p),R);
		update(L);
	}
	else
	{
		R=p;
		Split(val,ls(p),L,ls(p));
		update(R);
	}
	return;
}
int Merge(int L,int R)
{
	if(!L||!R) return L|R;
	if(tree[L].dat>tree[R].dat)
	{
		rs(L)=Merge(rs(L),R);
		update(L);
		return L;
	}
	else
	{
		ls(R)=Merge(L,ls(R));
		update(R);
		return R;
	}
	return 0;
}

void Insert(int val)
{
	int p=create(val);
	int L,R; Split(val,root,L,R);
	root=Merge(L,Merge(p,R));
	return;
}
void Remove(int val)
{
	int NR,R; Split(val,root,NR,R);
	int L,MID; Split(val-1,NR,L,MID);
	MID=Merge(ls(MID),rs(MID));
	root=Merge(L,Merge(MID,R));
	return;
}

int get_rank(int val)
{
	int L,R; Split(val-1,root,L,R);
	int res=tree[L].sz+1;
	root=Merge(L,R);
	return res;
}
int get_value(int rank)
{
	int p=root;
	while(p)
	{
		int lsz=tree[ls(p)].sz;
		if(rank==lsz+1) return tree[p].val;
		if(rank<=lsz) p=ls(p);
		else rank-=lsz+1,p=rs(p);
	}
	return -1;
}

int get_prev(int val)
{
	return get_value(get_rank(val)-1);
}
int get_next(int val)
{
	return get_value(get_rank(val+1));
}

}

int main()
{
	read(n),read(m);
	for(int i=1;i<=n;i++)
	{
		read(a[i]);
		FHQ::Insert(a[i]);
	}
	int last=0,ans=0;
	for(int i=1;i<=m;i++)
	{
		int op,x; read(op),read(x);
		x^=last;
		switch(op)
		{
			case 1:
				FHQ::Insert(x);
				break;
			case 2:
				FHQ::Remove(x);
				break;
			case 3:
				last=FHQ::get_rank(x);
				ans^=last;
				break;
			case 4:
				last=FHQ::get_value(x);
				ans^=last;
				break;
			case 5:
				last=FHQ::get_prev(x);
				ans^=last;
				break;
			case 6:
				last=FHQ::get_next(x);
				ans^=last;
				break;
		}
	}
	write(ans,'\n');
	return 0;
}

P3391 【模板】文艺平衡树

这道题只用了 FHQ Treap,真的爽。

此题中 \(val\) 值不再是静态的,因为有交换子树的操作,也不可能是静态的。

这个动态的 \(val\) 就是数列的下标,下标完美满足 BST 的所有条件:某个数左边数的下标都比它小,而右边都比它大。

而这个下标既然是动态的,自然不能存起来在分割函数内动态地就可以获取当前节点的下标

这种方法理论上扩展性很强,区间问题都可以这么转换。

完整代码:

点击查看代码
#include<cstdio>
#include<random>
#include<chrono>
using namespace std;

namespace IO{
template<typename TYPE> void read(TYPE &x)
{
	x=0; bool neg=false; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')neg=true;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+(ch^'0');ch=getchar();}
	if(neg){x=-x;} return;
}
template<typename TYPE> void write(TYPE x)
{
	if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;}
	static int sta[55];int statop=0; while(x){sta[++statop]=x%10;x/=10;}
	while(statop){putchar('0'+sta[statop--]);} return;
}
template<typename TYPE> void write(TYPE x,char ch){write(x);putchar(ch);return;}
} using namespace IO;

const int N=1e5+5,M=1e5+5;
int n,m;

namespace FHQ{

struct Treap{
	int ls,rs;
	int id,dat;
	bool lazy;
	int sz;
}tree[M];
int idx,root;
#define ls(p) tree[p].ls
#define rs(p) tree[p].rs

mt19937 engine(chrono::steady_clock::now().time_since_epoch().count());
inline int create(int id)
{
	tree[++idx]={0,0,id,(int)engine(),false,1};
	return idx;
}
inline void update(int p)
{
	tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+1;
	return;
}
void spread(int p)
{
	if(tree[p].lazy)
	{
		tree[ls(p)].lazy^=true;
		tree[rs(p)].lazy^=true;
		swap(ls(p),rs(p));
		tree[p].lazy=false;
	}
	return;
}

void Split(int pos,int p,int &L,int &R)
{
	if(!p){L=R=0; return;}
	spread(p);
	if(tree[ls(p)].sz+1<=pos)
	{
		L=p;
		Split(pos-(tree[ls(p)].sz+1),rs(p),rs(p),R);
		update(L);
	}
	else
	{
		R=p;
		Split(pos,ls(p),L,ls(p));
		update(R);
	}
	return;
}
int Merge(int L,int R)
{
	if(!L||!R) return L|R;
	if(tree[L].dat>tree[R].dat)
	{
		spread(L);
		rs(L)=Merge(rs(L),R);
		update(L);
		return L;
	}
	else
	{
		spread(R);
		ls(R)=Merge(L,ls(R));
		update(R);
		return R;
	}
}

void Reverse(int l,int r)
{
	int NR,R; Split(r,root,NR,R);
	int L,MID; Split(l-1,NR,L,MID);
	tree[MID].lazy^=true;
	root=Merge(Merge(L,MID),R);
	return;
}

void DFS(int p)
{
	if(!p) return;
	spread(p);
	DFS(ls(p));
	write(tree[p].id,' ');
	DFS(rs(p));
	return;
}

} using namespace FHQ;

int main()
{
	read(n),read(m);
	for(int i=1;i<=n;i++)
		root=Merge(root,create(i));
	for(int i=1;i<=m;i++)
	{
		int l,r; read(l),read(r);
		Reverse(l,r);
	}
	DFS(root);
	return 0;
}

标签:总结,return,val,rs,int,练习,tree,ls,平衡
From: https://www.cnblogs.com/jerrycyx/p/18546756

相关文章

  • 11月13日总结
    今天学习了搜索算法比较难也比较麻烦搜索算法是利用计算机的高性能来有目的的穷举一个问题解空间的部分或所有的可能情况,从而求出问题的解的一种方法。现阶段一般有枚举算法、深度优先搜索、广度优先搜索、A*算法、回溯算法、蒙特卡洛树搜索、散列函数等算法。在大规模实验环境......
  • c语言知识点总结-字符串、思维导图
    字面串、字符串变量、字符串的读写、字符串中字符的访问、函数、字符串处理操作、字符串数组总结。文中链接:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/143772084锦黎pro-CSDN博客锦黎pro擅长c语言知识点总结、思维导图,等方面的知识https://blog.csdn.net/jilipro?......
  • netCore物联网项目,分布式部署方案总结
    十年河东,十年河西,莫欺少年穷学无止境,精益求精部署环境:2台windowsServe服务器,2台linux服务器,阿里云CLB负载均衡服务器(2个),阿里云RabbitMQ,阿里云Ots表格存储(用于存物联网设备上报数据),Sqlserver服务器(存放业务主数据),Postgresql服务器(短期存放非业务主数据),阿里云Redis实例,对象存储OSS......
  • 2024.11.14随笔&联考总结
    前言今天联考直接炸纲了。但是不得不说:HEZ的题要比BSZX好多了。联考今天联考题说实话难度应该比较适合我。第一题是推结论的题,我赛时20min想出正解,但是有两个细节没有考虑清楚,导致后来调题调了一个多小时,然后经典开警告但是不看秒了,期望得分100pts,实际0pts。原因bool......
  • 【数学】线性代数知识点总结
    0.前言线性代数是数学的一个分支,线性代数的研究对象是向量、向量空间(又称线性空间),线性变换和有限维的线性方程组。即线性代数主要处理线性关系问题,线性关系即数学对象之间的关系是以一次形式来表达的。线性(Linear)是指量与量之间按比例、成直线的关系,在数学上可以理解为一......
  • vue中百度地图切换高德地图总结
    由于公司不续费百度地图,所以切换高德。。。一、注册高德需要这样,先安装@amap/amap-jsapi-loaderimportAMapLoaderfrom"@amap/amap-jsapi-loader";mapInit(point){window._AMapSecurityConfig={//安全密钥securityJsCode:"*********",//换成自己的}......
  • SQL知识与练习
    目录SQL知识与练习日期ROW_NUMBER、SUBSTR、SUBSTR和COALESCE方法LIKE、INNERJOIN、LEFTOUTERJOINSQL知识与练习日期--查询当年当月当天过去七天某个日期后的30天--SELECT*FROMods_bctulmarketWHEREbusinessdateBETWEEN'2024-01-01'AND'2024-12-31';--......
  • Python练习2:企业发放的奖金根据利润提成。利润([)低于或等于10万元时,奖金可提10%;利润
     Python练习2:企业发放的奖金根据利润提成。利润([)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时......
  • 每日总结43
    下载python库缓慢时,可以更改为国内的镜像使用国内镜像源:由于pip默认从PyPI下载,而PyPI的服务器在国外,导致下载速度慢。您可以更换为国内的镜像源来加速下载。以下是几个常用的国内镜像源:清华大学:https://pypi.tuna.tsinghua.edu.cn/simple阿里云:https://mirrors.aliyun.com......
  • Unity类银河战士恶魔城学习总结(P124 Limit Inventory Slots 限制库存槽位)
    【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/本章节实现了仓库满了不能添加物品,而且会摧毁物品的Bug并且增加了背包满了拾取物品的一个小动画ItemObject.csusingSystem.Collections;usingSyst......