DS

DS

前言

把所有学过的ds整合一下,不然太难受惹qwq

Part1-树状数组

#define lowbit(x) (x&-x) 
int n,m,c[N],a;
void add(int x,int k){
	while(x<=N){
		c[x]+=k;
		x+=lowbit(x);
	}
}
int sum(int x){
	int res=0;
	while(x){
		res+=c[x];
		x-=lowbit(x);
	}
	return res;
}

Part2-ST表

void pre(){
	longn[1]=0;
	longn[2]=1;
	for(int i=3;i<maxn;i++)
		longn[i]=longn[i/2]+1;
}

int main(){
	int n=read(),m=read();
	for(int i=1;i<=n;i++)
		d[i][0]=read();
	pre();
	for(int j=1;j<=logn;j++)
		for(int i=1;i+(1<<j)-1<=n;i++)
			d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
	for(int i=1;i<=m;i++){
		int x=read(),y=read();
		int s=longn[y-x+1];
		printf("%d\n",max(d[x][s],d[y-(1<<s)+1][s]));
	}
	return 0;
}

Part3-线段树

朴素

#define ls (p<<1)
#define rs (p<<1|1)
ll a[MAX], sum[MAX * 4], ch[MAX * 4], laz[MAX * 4]; 
void get(int p) {
	sum[p] = (sum[ls] + sum[rs]) % mod;
}
void pushdown (int s, int t, int p) {
	int mid = s + ((t - s) >> 1);
	if (ch[p] != 1) {
		ch[ls] *= ch[p], ch[ls] %= mod;
		ch[rs] *= ch[p], ch[rs] %= mod;
		laz[ls] *= ch[p], laz[ls] %= mod;
		laz[rs] *= ch[p], laz[rs] %= mod;
		sum[ls] *= ch[p], sum[ls] %= mod;
		sum[rs] *= ch[p], sum[rs] %= mod;
		ch[p] = 1;
	}
	if (laz[p]) {
		sum[ls] += laz[p] * (mid - s + 1), sum[ls] %= mod;
 	    sum[rs] += laz[p] * (t - mid), sum[rs] %= mod;
   		laz[ls] += laz[p], laz[ls] %= mod;
    	laz[rs] += laz[p], laz[rs] %= mod;
    	laz[p] = 0;
	}
	return;
}
//建树 
void build(int s,int t,int p){
	ch[p] = 1;
	if (s == t) {
		sum[p] = a[s];
		return;
	}
	int mid = (s + ((t - s) >> 1));
	build(s ,mid ,ls);
	build(mid + 1 ,t , rs); 
	get(p); 
	return;
} 
//区间乘 
void by(int l, int r, ll b, int s, int t, int p){
	int mid = s + ((t - s) >> 1);
	if (l <= s && t <= r) {
		ch[p] *= b, ch[p] %= mod;
		laz[p] *= b, laz[p] %= mod;
		sum[p] *= b, sum[p] %= mod;
		return;
	}
	pushdown(s, t, p);
	if (l <= mid ) by(l, r, b, s, mid, ls) ;
	if (r > mid ) by(l, r, b, mid + 1, t, rs) ;
	get(p);
	return;
}
//区间修改 +
void add(int l,int r,int c,int s,int t,int p){
	int mid = s + ((t - s) >> 1);
	if (l <= s && t <= r){ 
		sum[p] += 1ll * (t - s + 1) * c, sum[p] %= mod;
		laz[p] += c, laz[p] %= mod; 
		return ;
	} 
	pushdown(s, t, p);
	if (l <= mid) add(l ,r ,c ,s ,mid ,ls); 
	if (r > mid) add(l ,r ,c ,mid + 1,t ,rs);
	get(p);
	return;
}
ll getsum(int l,int r,int s,int t,int p){
	int mid = s + ((t - s) >> 1);
	ll ans = 0;
	if (l <= s && r >= t) 
	    return sum[p] % mod;
	pushdown(s, t, p);
	if (l <= mid) ans += getsum(l ,r ,s ,mid ,ls);
	ans %= mod; 
	if (r > mid) ans += getsum(l ,r ,mid + 1 ,t ,rs);
	ans %= mod;
	return ans % mod;
}

咳咳,看到之前的码风,差点猝死(

线段树合并+分裂

#define N 200050
#define ll long long
int n,m;
int rt[N],tot,cnt;
int bac[N<<5],ct;
void Del(int y){
	bac[++ct]=y;
	t[y].ls=t[y].rs=t[y].v=0;
}
int New(){
	return ct?bac[ct--]:++tot;
}
void pushup(int p){
	t[p].v=t[t[p].ls].v+t[t[p].rs].v;
}
int merge(int a,int b,int l,int r){
	if(!a||!b){
		return a|=b;	
	}
	if(l==r){
		t[a].v+=t[b].v;
		return a;
	}
	int mid=l+r>>1;
	t[a].ls=merge(t[a].ls,t[b].ls,l,mid);
	t[a].rs=merge(t[a].rs,t[b].rs,mid+1,r);
	pushup(a);
	Del(b);
	return a;
}
int split(int a,int b,ll k){
	if(!a)return a;
	b=New();
	ll v=t[t[a].ls].v;
	if(v<k)t[b].rs=split(t[a].rs,t[b].rs,k-v);
	else std::swap(t[a].rs,t[b].rs);
	if(v>k)t[b].ls=split(t[a].ls,t[b].ls,k);
	t[b].v=t[a].v-k;
	t[a].v=k;
	return b;
}
int kth(int p,int l,int r,int k){//一般分裂用来求第k小
	if(l==r)return l;
	int mid=l+r>>1;
	if(k<=t[t[p].ls].v)return kth(t[p].ls,l,mid,k);
	else return kth(t[p].rs,mid+1,r,k-t[t[p].ls].v);
}

这才是狼狼的码风,上面是权值树嗷。

可持久化线段树

#define N 1000005
int n,m,tot,len;
int a[N],b[N],rt[N];
int sum[N<<5],ls[N<<5],rs[N<<5];
int build(int l,int r){
	int root=++tot;
	sum[root]=0;
	if(l==r)return root;
	int mid=(l+r)>>1;
	ls[root]=build(l,mid);
	rs[root]=build(mid+1,r);
	return root;
}
int update(int k,int l,int r,int root){//root上个版本 
	int x=++tot;
	ls[x]=ls[root],rs[x]=rs[root],sum[x]=sum[root]+1;
	if(l==r)return x;
	int mid=(l+r)>>1;
	if(k<=mid){
		ls[x]=update(k,l,mid,ls[x]);
	}
	else{
		rs[x]=update(k,mid+1,r,rs[x]);
	}
	return x;
}
int query(int u,int v,int l,int r,int k){//(u,v)第k小 
	int x=sum[ls[v]]-sum[ls[u]];
	int mid=(l+r)>>1;
	if(l==r)return l;
	if(k<=x){
		return query(ls[u],ls[v],l,mid,k);
	}
	else return query(rs[u],rs[v],mid+1,r,k-x);
}

下面是可持久化并查集

#define N 200050
#define ls t[p].lson
#define rs t[p].rson
#define v t[p].val
#define fa t[p].f
#define mid (l+r>>1)
#define max(x,y) (x>y?x:y)
int n,m,rt[N],tot;
struct segtree{
	int val,f,lson,rson;
}t[N*50];
int build(int l,int r){
	int p=++tot;
	if(l==r){
		v=1;fa=l;return p;
	}
	ls=build(l,mid);
	rs=build(mid+1,r);
	return p;
}
int query_fa(int p,int l,int r,int pos){
	if(l==r)return fa;
	if(pos<=mid)return query_fa(ls,l,mid,pos);
	else return query_fa(rs,mid+1,r,pos);
}
int query_rk(int p,int l,int r,int pos){
	if(l==r)return v;
	if(pos<=mid)return query_rk(ls,l,mid,pos);
	else return query_rk(rs,mid+1,r,pos);
}
int upd_val(int now,int l,int r,int pos,int vv){
	int p=++tot;
	t[p]=t[now];
	if(l==r){
		v=max(v,vv);return p;
	}
	if(pos<=mid)ls=upd_val(t[now].lson,l,mid,pos,vv);
	else rs=upd_val(t[now].rson,mid+1,r,pos,vv);
	return p;
}
int upd_fa(int now,int l,int r,int pos,int f){
	int p=++tot;
	t[p]=t[now];
	if(l==r){
		fa=f;return p;
	}
	if(pos<=mid)ls=upd_fa(t[now].lson,l,mid,pos,f);
	else rs=upd_fa(t[now].rson,mid+1,r,pos,f);
	return p;
}
int find(int p,int pos){
	int f=query_fa(p,1,n,pos);
	if(f==pos)return f;
	else return find(p,f);
}

李超线段树

#define N 201005
#define eps 1e-9
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
#define pdi pair<double,int>
#define f first
#define s second
#define mod 39989
#define mod1 1000000000
using std::pair;
struct line {
	double k,b;
}l[N];
int s[N],cnt,n,lastans,x,xx,y,yy,op;
int cmp(double x,double y){//x>y 
	if(x-y>eps)return 1;
	if(y-x>eps)return -1;
	return 0;
}
double cale(int id,int x){//计算值 
	return l[id].b+l[id].k*x;
}
void add(int x,int y,int xx,int yy){//加入直线 
	cnt++;
	if(x==xx){
		l[cnt].k=0;l[cnt].b=std::max(y,yy);
	}
	else {
		l[cnt].k=1.0*(yy-y)/(xx-x);l[cnt].b=1.0*(yy-xx*l[cnt].k);
	}
}
void upd(int p,int l,int r,int u){
	int&v=s[p];
	if(cmp(cale(u,mid),cale(v,mid))==1)std::swap(u,v);
	int bl=cmp(cale(u,l),cale(v,l)),br=cmp(cale(u,r),cale(v,r));
	if(bl==1||(!bl&&u<v))upd(ls,l,mid,u);
	if(br==1||(!br&&u<v))upd(rs,mid+1,r,u);
}
void update(int p,int l,int r,int x,int y,int k){
	if(l>=x&&r<=y){
		upd(p,l,r,k);
		return;
	}
	if(x<=mid)update(ls,l,mid,x,y,k);
	if(y>mid)update(rs,mid+1,r,x,y,k);
}
pdi pmax(pdi a,pdi b){//比较大小 
	if(cmp(a.f,b.f)==1){
		return a;
	}
	if(cmp(a.f,b.f)==-1){
		return b;
	}
	return a.s<b.s?a:b;
}
pdi query(int p,int l,int r,int k){//查询 x=k 时的最大y 
	if(k<l||k>r)return{0,0};
	double res=cale(s[p],k);
	if(l==r)return  {res,s[p]};
	return pmax({res,s[p]},pmax(query(ls,l,mid,k),query(rs,mid+1,r,k)));
}

下面是斜率优化用滴


db g(int m,int x){
	return (db)(l[m].k*x+l[m].b);
}
void change(int&p,ll l,ll r,int t){
	if(!p){
		p=++idx;
		tr[p].id=t;
	}
	ll mid=l+r>>1;
	if(l==r)return;
	if(g(t,mid)<g(tr[p].id,mid))std::swap(t,tr[p].id);
	if(g(t,l)<g(tr[p].id,l))change(tr[p].ls,l,mid,t);
	else if(g(t,r)<g(tr[p].id,r))change(tr[p].rs,mid+1,r,t); 
}
db qry(int p,ll l,ll r){
	if(!p)return INF;
	if(l==r){
		return g(tr[p].id,u);
	}
	db ret=g(tr[p].id,u);
	ll mid=l+r>>1;
	return std::min(ret,u<=mid?qry(tr[p].ls,l,mid):qry(tr[p].rs,mid+1,r));
}

简化了不少,还用了动开()

Part4-trie树

朴素

#define N 525500
#define ls ch[x][0]
#define rs ch[x][1]
int ch[N*25][2],rt[N],w[N*25],sum[N*25],cnt;
void maintain(int x){
	w[x]=sum[x]=0;
	if(ls){
		w[x]+=w[ls];
		sum[x]^=(sum[ls]<<1);
	}
	if(rs){
		w[x]+=w[rs];
		sum[x]^=(sum[rs]<<1)|(w[rs]&1);
	}
}
int makenew(){
	int x=++cnt;ch[x][0]=ch[x][1]=w[x]=sum[x]=0;
	return x;
}
void insert(int&x,int k,int dep){
	if(!x)x=makenew();
	if(dep>23)return (void)(w[x]++);
	insert(ch[x][k&1],k>>1,dep+1);
	maintain(x);
}
void addall(int x){
	std::swap(ls,rs);
	if(ls)addall(ls);
	maintain(x);
}
int merge(int x,int y){
	if(!x||!y)return x^y;
	w[x]+=w[y];
	sum[x]^=sum[y];
	ls=merge(ls,ch[y][0]);
	rs=merge(rs,ch[y][1]);
	return x;
}

可持久化01trie

#define N 600050
#define _N N*33
#define ls ch[x][0]
#define rs ch[x][1]
int ver[_N],ch[_N][2],sum[_N],rt[N],cnt;
int n,m,s[N];
void insert(int now,int lst,int k){//这里注意一下ver表示的是哪个版本就OK了
	for(int i=28;i>=0;i--){
		ver[now]=ver[lst]+1;
		int b=(k>>i)&1;
		if(!ch[now][b])ch[now][b]=++cnt;
		ch[now][!b]=ch[lst][!b];
		now=ch[now][b];
		lst=ch[lst][b];
	}
	ver[now]=ver[lst]+1;
}
int qry(int l,int r,int k){//(l,r)求异或k的最大值
	int res=0;
	for(int i=28;i>=0;i--){
		int b=(k>>i)&1;
		if(ver[ch[r][!b]]-ver[ch[l][!b]]){//判断区间内有没有
			res^=(1<<i);
			r=ch[r][!b];l=ch[l][!b];
		}
		else r=ch[r][b],l=ch[l][b];
	}
	return res;
}

Part5-平衡树

treap

#define mt  make_tuple
#define f first
#define s second
std::mt19937 myrand(0);
using std::pair;
using std::tuple;
using std::make_tuple;
using std::tie;
struct Node{
	Node*ch[2];
	int val,p,siz,cnt;
	Node(Node*node){
		val=node->val;p=node->p;siz=node->siz;cnt=node->cnt;
	} 
	Node(int val):val(val),siz(1),cnt(1){
		ch[0]=ch[1]=nullptr;
		p=myrand();
	}
	void upd_siz(){
		siz=cnt;
		if(ch[0]!=nullptr)siz+=ch[0]->siz;
		if(ch[1]!=nullptr)siz+=ch[1]->siz;
	}
};
struct non_xuan_treap{
	Node*root;
	pair<Node*,Node*>split(Node*cur,int val){
		if(cur==nullptr)return {nullptr,nullptr};
		if(cur->val>val){
			auto temp=split(cur->ch[0],val);
			cur->ch[0]=temp.s;
			cur->upd_siz();
			return {temp.f,cur};
		}
		else{
			auto temp=split(cur->ch[1],val);
			cur->ch[1]=temp.f;
			cur->upd_siz();
			return {cur,temp.s};
		}
	}
	tuple<Node*,Node*,Node*>split_by_rk(Node*cur,int rk){
		if(cur==nullptr)return mt(nullptr,nullptr,nullptr);
		int ls=cur->ch[0]==nullptr?0:cur->ch[0]->siz;
		if(rk<=ls){
			Node*l,*mid,*r;
			tie(l,mid,r)=split_by_rk(cur->ch[0],rk);
			cur->ch[0]=r;//
			cur->upd_siz();
			return mt(l,mid,cur);
		}
		else if(rk<=ls+cur->cnt){
			Node*l=cur->ch[0];
			Node*r=cur->ch[1];
			cur->ch[0]=cur->ch[1]=nullptr;
			cur->upd_siz();
			return mt(l,cur,r);
		}
		else{
			Node*l,*mid,*r;
			tie(l,mid,r)=split_by_rk(cur->ch[1],rk-ls-cur->cnt);
			cur->ch[1]=l;//
			cur->upd_siz();
			return mt(cur,mid,r);
		}
	}
	Node*merge(Node*u,Node*v){
		if(u==nullptr&&v==nullptr)return nullptr;
		if(u!=nullptr&&v==nullptr)return u;
		if(u==nullptr&&v!=nullptr)return v;
		if(u->p<v->p){
			u->ch[1]=merge(u->ch[1],v);
			u->upd_siz();
			return u;
		}
		else{
			v->ch[0]=merge(u,v->ch[0]);
			v->upd_siz();
			return v;
		}
	}
	void insert(int val){
		auto temp=split(root,val);
		auto ll=split(temp.f,val-1);
		Node*new_;
		if(ll.s==nullptr){
			new_=new Node(val);
		}
		else{
			ll.s->cnt++;
			ll.s->upd_siz();
		}
		auto l=merge(ll.f,ll.s==nullptr?new_:ll.s);
		root=merge(l,temp.s);
	}
	void del(int val){
		auto temp=split(root,val);
		auto ll=split(temp.f,val-1);
		if(ll.s->cnt>1){
			ll.s->cnt--;
			ll.s->upd_siz();
		}
		else{
			if(temp.f==ll.s){
				temp.f=nullptr;//
			}
			delete ll.s;
			ll.s=nullptr;
		}
		auto l=merge(ll.f,ll.s);
		root=merge(l,temp.s);
	}
	int qrank_by_val(Node*cur,int val){
		auto temp=split(cur,val-1);
		int ret=(temp.f==nullptr?0:temp.f->siz)+1;
		root=merge(temp.f,temp.s);
		return ret;
	}
	int qval_by_rank(Node*cur,int rk){
		Node*l,*mid,*r;
		tie(l,mid,r)=split_by_rk(cur,rk);
		int ret=mid->val;
		root=merge(merge(l,mid),r);
		return ret;
	}
	int q_beforeval(int val){
		auto temp=split(root,val-1);
		int ret=qval_by_rank(temp.f,temp.f->siz);
		root=merge(temp.f,temp.s);
		return ret;
	}
	int q_laterval(int val){
		auto temp=split(root,val);
		int ret=qval_by_rank(temp.s,1);
		root=merge(temp.f,temp.s);
		return ret;
	}
}T;

装逼写的指针xwx

splay

#define N 200006
struct node{
	int ch[2];
	int siz,val,tag,fa;
	void init(int v,int f){
		ch[0]=ch[1]=0;
		val=v;fa=f;tag=0;siz=1;
	}
}s[N];
int root,n,m,tot,l,r;
void pushup(int p){
	s[p].siz=s[s[p].ch[0]].siz+s[s[p].ch[1]].siz+1;
}
void pushdown(int p){
	if(s[p].tag){
		s[s[p].ch[0]].tag^=1;
		s[s[p].ch[1]].tag^=1;
		s[p].tag=0;
		std::swap(s[p].ch[0],s[p].ch[1]);
	}
}
void rot(int x){
	int y=s[x].fa,z=s[y].fa,k=s[y].ch[1]==x;
	if(z)
		s[z].ch[s[z].ch[1]==y]=x;
	s[x].fa=z;
	s[y].ch[k]=s[x].ch[k^1];
	s[s[x].ch[k^1]].fa=y;
	s[x].ch[k^1]=y;
	s[y].fa=x;
	pushup(x);pushup(y);
}
void splay(int x,int goal){
	while(s[x].fa!=goal){
		int y=s[x].fa,z=s[y].fa;
		if(z!=goal)
			rot((s[y].ch[1]==x)^(s[z].ch[1]==y)?x:y);
		rot(x);
	}
	if(goal==0)root=x;
}
int kth(int k){
	int u=root;
	while(1){
		pushdown(u);
		if(k<=s[s[u].ch[0]].siz)u=s[u].ch[0];
		else if(s[s[u].ch[0]].siz+1==k)return u;
		else k-=s[s[u].ch[0]].siz+1,u=s[u].ch[1];
	}
}
void insert(int x){
	int u=root,f=0;
	while(u)f=u,u=s[u].ch[x>s[f].val];
	u=++tot;
	if(f)
		s[f].ch[x>s[f].val]=u;
	s[u].init(x,f);
	splay(u,0);
}

Part-6动态树

LCT

#define N 300050
#define ls ch[x][0]
#define rs ch[x][1]
#define isroot(x) (ch[f[x]][0]!=x&&ch[f[x]][1]!=x)
#define get(x) (ch[f[x]][1]==x)
int n,m,ch[N][2],f[N],s[N],v[N],r[N],top,st[N];
void pushup(int x){
	s[x]=s[ls]^s[rs]^v[x];
}
void pushr(int x){
	std::swap(ls,rs);
	r[x]^=1;
}
void pushdown(int x){
	if(r[x]){
		if(ls)pushr(ls);
		if(rs)pushr(rs);
		r[x]=0;
	}
}
void rotate(int x){
	int y=f[x],z=f[y],k=get(x);
	if(!isroot(y))ch[z][get(y)]=x;
	ch[y][k]=ch[x][!k],f[ch[x][!k]]=y;
	ch[x][!k]=y,f[y]=x,f[x]=z;
	pushup(y);pushup(x);
}
void splay(int x){
	top=1;st[top]=x;
	for(int i=x;!isroot(i);i=f[i])st[++top]=f[i];
	for(int i=top;i;i--)pushdown(st[i]);
	for(int fa;fa=f[x],!isroot(x);rotate(x))
		if(!isroot(fa))rotate(get(fa)==get(x)?fa:x);
}
void access(int x){
	for(int p=0;x;x=f[p=x])
		splay(x),rs=p,pushup(x);
}
void makeroot(int x){
	access(x);splay(x);pushr(x);
}
int findroot(int x){
	access(x);
	splay(x);
	while(ls)pushdown(x),x=ls;
	splay(x);
	return x;
}
void split(int x,int y){
	makeroot(x);access(y);splay(y);
}
void link(int x,int y){
	makeroot(x);
	if(findroot(y)==x)return;
	f[x]=y;
}
void cut(int x,int y){
	makeroot(x);
	if(findroot(y)!=x||f[y]!=x||ch[y][0])return;
	f[y]=rs=0;pushup(x);
}
posted @ 2023-07-18 12:12  EnderWave  阅读(173)  评论(0)    收藏  举报