首页 > 其他分享 >模版汇总(1)

模版汇总(1)

时间:2024-11-28 20:24:57浏览次数:7  
标签:cnt return int 模版 汇总 tr rd edge

第一部分,主要以数据结构和图论为主。

遗漏了许多,懒得补了。

0.快读

为了观感,之后的代码就将前面这几行去掉了。

#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define gc getchar()
#define dg(ch) isdigit(ch)
#define _mul(x) ((x<<3)+(x<<1))
#define ll long long
#define il inline
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i>=k;i--)
il int read(){int x=0,f=1;char ch=gc;while(!dg(ch)){if(ch=='-')f=-1;ch=gc;}while(dg(ch))x=_mul(x)+(ch^48),ch=gc;return x*f;}

1.线段树维护区间加、区间乘、区间和

先乘后加。

...
const int N=1e5+10;
int n,q,mod,a[N];ll sum[N<<2],add[N<<2],mul[N<<2];
int MOD(int x){return x>=mod?x-mod:x;}
struct SMT{
	#define mid ((l+r)>>1)
	#define ls (u<<1)
	#define rs (u<<1|1)
	void pushdown(int u,int l,int r){
		sum[ls]=MOD(1ll*sum[ls]*mul[u]%mod+1ll*(mid-l+1)*add[u]%mod);
		sum[rs]=MOD(1ll*sum[rs]*mul[u]%mod+1ll*(r-mid)*add[u]%mod);
		mul[ls]=1ll*mul[ls]*mul[u]%mod,mul[rs]=1ll*mul[rs]*mul[u]%mod;
		add[ls]=MOD(1ll*add[ls]*mul[u]%mod+add[u]),add[rs]=MOD(1ll*add[rs]*mul[u]%mod+add[u]);
		add[u]=0,mul[u]=1;
	}
	void pushup(int u){sum[u]=sum[ls]+sum[rs];}
	void build(int u,int l,int r){
		mul[u]=1;
		if(l==r){sum[u]=a[l];return;}
		build(ls,l,mid),build(rs,mid+1,r),pushup(u);
	}
	void modify(int u,int l,int r,int ql,int qr,int ad,int mu){
		if(ql<=l&&r<=qr){
			sum[u]=MOD(1ll*sum[u]*mu%mod+1ll*(r-l+1)*ad%mod);
			mul[u]=1ll*mul[u]*mu,add[u]=MOD(1ll*add[u]*mu%mod+ad);
			return;
		}
		pushdown(u,l,r);
		if(ql<=mid) modify(ls,l,mid,ql,qr,ad,mu);
		if(qr>mid) modify(rs,mid+1,r,ql,qr,ad,mu);
		pushup(u);
	}
	int query(int u,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr) return sum[u];
		pushdown(u,l,r);int ans=0;
		if(ql<=mid) ans=MOD(ans+query(ls,l,mid,ql,qr));
		if(qr>mid) ans=MOD(ans+query(rs,mid+1,r,ql,qr));
		return ans;
	}
	#undef mid
	#undef ls
	#undef rs
}S;
int main(){
	n=rd,q=rd,mod=rd;FOR(i,1,n) a[i]=rd%mod;
	S.build(1,1,n);
	while(q--){
		int op=rd,l=rd,r=rd,x;
		if(op==1) x=rd,S.modify(1,1,n,l,r,0,x%mod);
		else if(op==2) x=rd,S.modify(1,1,n,l,r,x%mod,1);
		else printf("%d\n",S.query(1,1,n,l,r));
	}
	return 0;
}

2.树状数组

单点加、区间查。

...
const int N=5e5+10;
int n,q,tr[N],a[N];
void add(int x,int y){for(int i=x;i<=n;i+=i&(-i))tr[i]+=y;}
int query(int x){int res=0;for(int i=x;i;i-=i&(-i))res+=tr[i];return res;}
int main(){
	n=rd,q=rd;FOR(i,1,n) a[i]=rd,add(i,a[i]);
	while(q--){
		int op=rd,l=rd,r=rd;
		if(op==1) add(l,r);
		else printf("%d\n",query(r)-query(l-1));
	}
	return 0;
}

3.st 表

...
const int N=1e5+10;
int n,m,f[N][20];
int query(int l,int r){
	int k=log2(r-l+1);
	return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main(){
	n=rd,m=rd;FOR(i,1,n) f[i][0]=rd;
	FOR(i,1,19) for(int j=1;(j+(1<<i-1))<=n;j++) f[j][i]=max(f[j][i-1],f[j+(1<<i-1)][i-1]);
	while(m--){
		int l=rd,r=rd;
		printf("%d\n",query(l,r));
	}
	return 0;
}

4.单调栈

const int N=3e6+10;
int n,a[N],stk[N],top,ans[N];
int main(){
	n=rd;FOR(i,1,n) a[i]=rd;
	ROF(i,n,1){
		while(top&&a[stk[top]]<=a[i]) top--;
		ans[i]=stk[top],stk[++top]=i;
	}
	FOR(i,1,n) printf("%d ",ans[i]);
	return 0;
}

5.树链剖分

const int N=1e5+10;
int n,m,rt,mod,sum[N<<2],tag[N<<2],w[N],head[N],tot;
int sz[N],son[N],fa[N],dep[N],nw[N],dfn[N],idx,top[N];
struct node{int to,nxt;}edge[N<<1];
void add(int x,int y){edge[++tot]={y,head[x]},head[x]=tot;}
int MOD(int x){return x>=mod?x-mod:x;}

struct SMT{
	#define mid ((l+r)>>1)
	#define ls (u<<1)
	#define rs (u<<1|1)
	void pushdown(int u,int l,int r){
		if(!tag[u]) return;
		tag[ls]=MOD(tag[ls]+tag[u]),tag[rs]=MOD(tag[rs]+tag[u]);
		sum[ls]=MOD(sum[ls]+1ll*(mid-l+1)*tag[u]%mod),sum[rs]=MOD(sum[rs]+1ll*(r-mid)*tag[u]%mod);
		tag[u]=0;
	}
	void pushup(int u){sum[u]=MOD(sum[ls]+sum[rs]);}
	void build(int u,int l,int r){
		if(l==r){sum[u]=nw[l];return;}
		build(ls,l,mid),build(rs,mid+1,r),pushup(u);
	}
	void modify(int u,int l,int r,int ql,int qr,int v){
		if(ql<=l&&r<=qr){
			tag[u]=MOD(tag[u]+v),sum[u]=MOD(sum[u]+1ll*(r-l+1)*v%mod);
			return;
		}
		pushdown(u,l,r);
		if(ql<=mid) modify(ls,l,mid,ql,qr,v);
		if(qr>mid) modify(rs,mid+1,r,ql,qr,v);
		pushup(u);
	}
	int query(int u,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr) return sum[u];
		pushdown(u,l,r);int ans=0;
		if(ql<=mid) ans=MOD(ans+query(ls,l,mid,ql,qr));
		if(qr>mid) ans=MOD(ans+query(rs,mid+1,r,ql,qr));
		return ans;
	}
	#undef mid
	#undef ls
	#undef rs
}S;

namespace HPD{
	void dfs1(int x,int fat){
		sz[x]=1,fa[x]=fat,dep[x]=dep[fat]+1;
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fat) continue;
			dfs1(y,x),sz[x]+=sz[y];
			if(sz[son[x]]<sz[y]) son[x]=y;
		}
	}
	void dfs2(int x,int t){
		dfn[x]=++idx,nw[idx]=w[x],top[x]=t;
		if(!son[x]) return;
		dfs2(son[x],t);
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fa[x]||y==son[x]) continue;
			dfs2(y,y);
		}
	}
	void tree_modify(int x,int y,int v){
		int fx=top[x],fy=top[y];
		while(fx!=fy){
			if(dep[fx]>=dep[fy]) S.modify(1,1,n,dfn[fx],dfn[x],v),x=fa[fx];
			else S.modify(1,1,n,dfn[fy],dfn[y],v),y=fa[fy];
			fx=top[x],fy=top[y];
		}
		if(dfn[x]<dfn[y]) S.modify(1,1,n,dfn[x],dfn[y],v);
		else S.modify(1,1,n,dfn[y],dfn[x],v);
	}
	int tree_query(int x,int y){
		int fx=top[x],fy=top[y],res=0;
		while(fx!=fy){
			if(dep[fx]>=dep[fy]) res=MOD(res+S.query(1,1,n,dfn[fx],dfn[x])),x=fa[fx];
			else res=MOD(res+S.query(1,1,n,dfn[fy],dfn[y])),y=fa[fy];
			fx=top[x],fy=top[y];
		}
		if(dfn[x]<dfn[y]) res=MOD(res+S.query(1,1,n,dfn[x],dfn[y]));
		else res=MOD(res+S.query(1,1,n,dfn[y],dfn[x]));
		return res;
	}
	int subtree_query(int x){return S.query(1,1,n,dfn[x],dfn[x]+sz[x]-1);}
	void subtree_modify(int x,int v){S.modify(1,1,n,dfn[x],dfn[x]+sz[x]-1,v);}
}
using namespace HPD;

int main(){
	n=rd,m=rd,rt=rd,mod=rd;FOR(i,1,n) w[i]=rd%mod;
	FOR(i,1,n-1){int x=rd,y=rd;add(x,y),add(y,x);}
	HPD::dfs1(rt,0),HPD::dfs2(rt,rt),S.build(1,1,n);
	while(m--){
		int op=rd,x,y,v;
		if(op==1) x=rd,y=rd,v=rd,HPD::tree_modify(x,y,v);
		else if(op==2) x=rd,y=rd,printf("%d\n",HPD::tree_query(x,y));
		else if(op==3) x=rd,v=rd,HPD::subtree_modify(x,v);
		else x=rd,printf("%d\n",HPD::subtree_query(x));
	}
	return 0;
}

6.树上 K 级祖先(重链剖分做法)

直接往上跳就行,时间复杂度 \(O(n\log n)\),会劣一些。

const int N=5e5+10;ui s;
int n,q,head[N],tot,rt;ll ans;
int sz[N],fa[N],son[N],dep[N],top[N],idx,D[N],dfn[N];
struct node{int to,nxt;}edge[N<<1];
void add(int x,int y){edge[++tot]={y,head[x]},head[x]=tot;}

namespace HPD{
	void dfs1(int x){
		sz[x]=1,dep[x]=dep[fa[x]]+1;
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fa[x]) continue;
			dfs1(y),sz[x]+=sz[y];
			if(sz[son[x]]<sz[y]) son[x]=y;
		}
	}
	void dfs2(int x,int t){
		top[x]=t,dfn[x]=++idx,D[idx]=x;
		if(!son[x]) return;
		dfs2(son[x],t);
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fa[x]||y==son[x]) continue;
			dfs2(y,y);
		}
	}
	int KA(int x,int k){
		while(k>=dep[x]-dep[top[x]]+1&&x!=rt){
			k-=dep[x]-dep[top[x]]+1;
			x=fa[top[x]];
		}
		return D[dfn[x]-k];
	}
}
using namespace HPD;

il ui get(ui x){
	x^=x<<13,x^=x>>17,x^=x<<5;
	return s=x; 
}
int main(){
	n=rd,q=rd,cin>>s;int la=0;
	FOR(i,1,n){
		fa[i]=rd;
		if(fa[i]!=0) add(i,fa[i]),add(fa[i],i);
		else rt=i;
	}
	HPD::dfs1(rt),HPD::dfs2(rt,rt);
	FOR(i,1,q){
		int x=((get(s)^la)%n)+1,k=(get(s)^la)%dep[x];
		la=HPD::KA(x,k),ans^=1ll*i*la;
	}
	printf("%lld\n",ans);
	return 0;
}

7.笛卡尔树

每个节点由键值二元组 \((k,w)\) 组成,通常先按 \(k\) 排好序,然后利用栈来建树。

const int N=1e7+10;
int n,a[N],stk[N],top,ls[N],rs[N];ll ans1=0,ans2=0;

namespace Dtree{
	void build(){
		FOR(i,1,n){
			int k=top;
			while(k&&a[stk[k]]>a[i]) k--;
			if(k) rs[stk[k]]=i;if(k<top) ls[i]=stk[k+1];
			stk[++k]=i,top=k;
		}
	}
}
using namespace Dtree;

int main(){
	n=rd;FOR(i,1,n) a[i]=rd;
	Dtree::build();
	FOR(i,1,n) ans1^=1ll*i*(ls[i]+1),ans2^=1ll*i*(rs[i]+1);
	printf("%lld %lld\n",ans1,ans2);
	return 0;
}

8.FHQ Treap

按值分裂。

const int N=1e5+10;
int n,rt,idx;
struct{int l,r,val,key,sz;}tr[N];

namespace FHQ{
	int get(int v){
		tr[++idx].val=v,tr[idx].key=rand(),tr[idx].sz=1;
		return idx;
	}
	void pushup(int u){tr[u].sz=tr[tr[u].l].sz+tr[tr[u].r].sz+1;}
	void split(int u,int v,int &x,int &y){
		if(!u){x=y=0;return;}
		if(tr[u].val<=v) x=u,split(tr[x].r,v,tr[x].r,y),pushup(x);
		else y=u,split(tr[y].l,v,x,tr[y].l),pushup(y);
	}
	int merge(int x,int y){
		if(!x||!y) return x^y;
		if(tr[x].key<tr[y].key){tr[x].r=merge(tr[x].r,y),pushup(x);return x;}
		else{tr[y].l=merge(x,tr[y].l),pushup(y);return y;}
	}
	void insert(int v){
		int x,y,z;
		split(rt,v,x,y),z=get(v),rt=merge(merge(x,z),y);
	}
	void del(int v){
		int x,y,z;
		split(rt,v,x,z),split(x,v-1,x,y),y=merge(tr[y].l,tr[y].r);
		rt=merge(merge(x,y),z);
	}
	int getrank(int v){
		int x,y,ans;
		split(rt,v-1,x,y),ans=tr[x].sz+1,rt=merge(x,y);
		return ans;
	}
	int getval(int u,int k){
		if(k==tr[tr[u].l].sz+1) return tr[u].val;
		if(k<tr[tr[u].l].sz+1) return getval(tr[u].l,k);
		return getval(tr[u].r,k-tr[tr[u].l].sz-1);
	}
	int getpre(int v){
		int x,y,ans;
		split(rt,v-1,x,y),ans=getval(x,tr[x].sz),rt=merge(x,y);
		return ans;
	}
	int getnxt(int v){
		int x,y,ans;
		split(rt,v,x,y),ans=getval(y,1),rt=merge(x,y);
		return ans;
	}
}
using namespace FHQ;

int main(){
	n=rd;
	while(n--){
		int op=rd,x=rd;
		if(op==1) FHQ::insert(x);
		else if(op==2) FHQ::del(x);
		else if(op==3) printf("%d\n",FHQ::getrank(x));
		else if(op==4) printf("%d\n",FHQ::getval(rt,x));
		else if(op==5) printf("%d\n",FHQ::getpre(x));
		else printf("%d\n",FHQ::getnxt(x));
	}
	return 0;
}

9.FHQ-Treap(区间翻转操作)

按大小分裂。

const int N=1e5+10;
int n,q,rt,idx;
struct node{int l,r,val,key,sz,tag;}tr[N];

namespace FHQ{
	#define ls (tr[u].l)
	#define rs (tr[u].r)
	int get(int v){
		tr[++idx].val=v,tr[idx].key=rand(),tr[idx].sz=1,tr[idx].tag=0;
		return idx;
	}
	void pushup(int u){tr[u].sz=tr[ls].sz+tr[rs].sz+1;}
	void pushdown(int u){
		if(!tr[u].tag) return;
		swap(ls,rs);
		tr[ls].tag^=1,tr[rs].tag^=1,tr[u].tag=0;
	}
	void split(int u,int k,int &x,int &y){
		if(!u){x=y=0;return;}
		pushdown(u);int res=tr[ls].sz+1;
		if(res<=k) x=u,split(tr[x].r,k-res,tr[x].r,y),pushup(x);
		else y=u,split(tr[y].l,k,x,tr[y].l),pushup(y);
	}
	int merge(int x,int y){
		if(!x||!y) return x^y;
		if(tr[x].key<tr[y].key){pushdown(x),tr[x].r=merge(tr[x].r,y),pushup(x);return x;}
		else{pushdown(y),tr[y].l=merge(x,tr[y].l),pushup(y);return y;}
	}
	void output(int u){
		if(!u) return;pushdown(u);
		output(ls),printf("%d ",tr[u].val),output(rs);
	}
	#undef ls
	#undef rs
}
using namespace FHQ;

int main(){
	n=rd,q=rd;FOR(i,1,n) rt=merge(rt,get(i));
	while(q--){
		int l=rd,r=rd,x,y,z;
		FHQ::split(rt,r,x,z),FHQ::split(x,l-1,x,y),tr[y].tag^=1,rt=FHQ::merge(merge(x,y),z);
	}
	FHQ::output(rt);
	return 0;
}

10.线段树合并

洛谷的板子题。

const int N=1e5+10;
int n,m,head[N],tot,ls[N*100],rs[N*100],mx[N*100],id[N*100],idx,rt[N],ans[N];
struct node{int to,nxt;}edge[N<<1];
void add(int x,int y){edge[++tot]={y,head[x]},head[x]=tot;}

namespace LCA{
	int f[N][20],dep[N];
	void dfs(int x,int fa){
		f[x][0]=fa,dep[x]=dep[fa]+1;
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fa) continue;
			dfs(y,x);
		}
	}
	void init(){FOR(i,1,19) FOR(j,1,n) f[j][i]=f[f[j][i-1]][i-1];}
	int lca(int x,int y){
		if(dep[x]>dep[y]) swap(x,y);
		int k=log2(dep[y]+1);
		ROF(i,k,0) if(dep[y]-(1<<i)>=dep[x]) y=f[y][i];
		if(x==y) return x;
		ROF(i,k,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
		return f[x][0];
	}
}
using namespace LCA;

namespace SMT{
	#define mid ((l+r)>>1)
	void pushup(int u){
		if(mx[ls[u]]>=mx[rs[u]]) mx[u]=mx[ls[u]],id[u]=id[ls[u]];
		else mx[u]=mx[rs[u]],id[u]=id[rs[u]];
	}
	void modify(int &u,int l,int r,int x,int v){
		if(!u) u=++idx;
		if(l==r){mx[u]+=v,id[u]=x;return;}
		if(x<=mid) modify(ls[u],l,mid,x,v);
		else modify(rs[u],mid+1,r,x,v);
		pushup(u);
	}
	int merge(int x,int y,int l,int r){
		if(!x||!y) return x^y;
		if(l==r){mx[x]+=mx[y];return x;}
		ls[x]=merge(ls[x],ls[y],l,mid),rs[x]=merge(rs[x],rs[y],mid+1,r);
		pushup(x);return x;
	}
	void Tmerge(int x,int fa){
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fa) continue;
			Tmerge(y,x),rt[x]=merge(rt[x],rt[y],1,1e5);
		}
		if(mx[rt[x]]>0) ans[x]=id[rt[x]];
	}
	#undef mid
}
using namespace SMT;

int main(){
	n=rd,m=rd;
	FOR(i,1,n-1){int x=rd,y=rd;add(x,y),add(y,x);}
	LCA::dfs(1,0),LCA::init();
	while(m--){
		int x=rd,y=rd,z=rd;
		SMT::modify(rt[x],1,1e5,z,1),SMT::modify(rt[y],1,1e5,z,1);
		SMT::modify(rt[LCA::lca(x,y)],1,1e5,z,-1);
		if(f[LCA::lca(x,y)][0]) SMT::modify(rt[f[LCA::lca(x,y)][0]],1,1e5,z,-1);
	}
	SMT::Tmerge(1,0);
	FOR(i,1,n) printf("%d\n",ans[i]);
	return 0;
}

11.倍增 LCA

const int N=5e5+10;
int n,m,rt,head[N],tot;
struct node{int to,nxt;}edge[N<<1];
void add(int x,int y){edge[++tot]={y,head[x]},head[x]=tot;}

namespace LCA{
	int f[N][20],dep[N];
	void dfs(int x,int fa){
		f[x][0]=fa,dep[x]=dep[fa]+1;
		for(int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;if(y==fa) continue;
			dfs(y,x);
		}
	}
	void init(){FOR(i,1,19) FOR(j,1,n) f[j][i]=f[f[j][i-1]][i-1];}
	int lca(int x,int y){
		if(dep[x]>dep[y]) swap(x,y);
		int k=log2(dep[y]+1);
		ROF(i,k,0) if(dep[y]-(1<<i)>=dep[x]) y=f[y][i];
		if(x==y) return x;
		ROF(i,k,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
		return f[x][0];
	}
}
using namespace LCA;

int main(){
	n=rd,m=rd,rt=rd;FOR(i,1,n-1){int x=rd,y=rd;add(x,y),add(y,x);}
	LCA::dfs(rt,0),LCA::init();
	while(m--){
		int x=rd,y=rd;
		printf("%d\n",LCA::lca(x,y));
	}
	return 0;
}

12.李超线段树

const int N=1e5+10,M=40000,mod=1e9;
const double eps=1e-12;
int n,seg[N<<2],cnt;
struct segment{double k,b;}p[N];
int cmp(double a,double b){
	if(a-b>=eps) return 1;
	if(b-a>=eps) return -1;
	return 0;
}
double cal(int cnt,int x){return p[cnt].k*x+p[cnt].b;}

namespace SMT{
	#define mid ((l+r)>>1)
	#define ls (u<<1)
	#define rs (u<<1|1)
	void update(int u,int l,int r,int c){
		int &g=seg[u],cm=cmp(cal(c,mid),cal(g,mid));
		if(cm==1||(cm==0&&c<g)) swap(g,c);
		int cl=cmp(cal(c,l),cal(g,l)),cr=cmp(cal(c,r),cal(g,r));
		if(cl==1||(cl==0&&c<g)) update(ls,l,mid,c);
		if(cr==1||(cr==0&&c<g)) update(rs,mid+1,r,c);
	}
	void modify(int u,int l,int r,int ql,int qr,int c){
		if(ql<=l&&r<=qr){update(u,l,r,c);return;}
		if(ql<=mid) modify(ls,l,mid,ql,qr,c);
		if(qr>mid) modify(rs,mid+1,r,ql,qr,c);
	}
	PDI pmx(PDI a,PDI b){
		if(cmp(a.fi,b.fi)>0) return a;
		if(cmp(a.fi,b.fi)<0) return b;
		if(a.se<b.se) return a;
		return b;
	}
	PDI query(int u,int l,int r,int x){
		if(l>x||r<x) return mp(-1e16,0);
		PDI res=mp(cal(seg[u],x),seg[u]);
		if(l==r) return res;
		return pmx(res,pmx(query(ls,l,mid,x),query(rs,mid+1,r,x)));
	}
	#undef mid
	#undef ls
	#undef rs
}
using namespace SMT;

int main(){
	n=rd;int la=0;p[0].b=-1e9;
	while(n--){
		int op=rd;
		if(op){
			int x0=rd,y0=rd,x1=rd,y1=rd;
			x0=(x0+la-1)%39989+1,x1=(x1+la-1)%39989+1;
			y0=(y0+la-1)%mod+1,y1=(y1+la-1)%mod+1;
			if(x0>x1) swap(x0,x1),swap(y0,y1);
			if(x0==x1){
				p[++cnt].k=0;int tmp=max(y0,y1);
				p[cnt].b=1.0*tmp;
			}
			else{
				p[++cnt].k=1.0*(y0-y1)/(x0-x1),p[cnt].b=-p[cnt].k*x0+y0;
			}
			SMT::modify(1,1,M,x0,x1,cnt);
		}
		else{
			int k=rd;k=(k+la-1)%39989+1;
			PDI res=SMT::query(1,1,M,k);
			la=res.se;printf("%d\n",la);
		}
	}
	return 0;
}

13.并查集

const int N=10010;
int n,m,fa[N];
int find(int x){if(x!=fa[x])fa[x]=find(fa[x]);return fa[x];}
void merge(int x,int y){if(find(x)==find(y))return;fa[find(x)]=find(y);}
int main(){
	n=rd,m=rd;FOR(i,1,n) fa[i]=i;
	FOR(i,1,m){
		int op=rd,x=rd,y=rd;
		if(op==1) merge(x,y);
		else puts(find(x)==find(y)?"Y":"N");
	}
	return 0;
}

14.堆优化 dijkstra

void dijkstra(int s){
	memset(vis,0,sizeof(vis)),memset(dist,0x3f,sizeof(dist));
	pq<PII,vector<PII>,greater<PII> > q;q.push(mp(0,s)),dist[s]=0;
	while(!q.empty()){
		int t=q.top().se;q.pop();
		if(vis[t]) continue;vis[t]=1;
		for(int i=head[t];i;i=edge[i].nxt){
			int y=edge[i].to;
			if(dist[y]>dist[t]+edge[i].w)
				dist[y]=dist[t]+edge[i].w,q.push(mp(dist[y],y));
		}
	}
}

15.Floyd

const int N=110;
int n,m,g[N][N];
int main(){
	n=rd,m=rd;memset(g,0x3f,sizeof(g));
	FOR(i,1,n) g[i][i]=0;
	FOR(i,1,m){int x=rd,y=rd,w=rd;g[x][y]=g[y][x]=min(g[x][y],w);}
	FOR(k,1,n) FOR(i,1,n) FOR(j,1,n) g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
	FOR(i,1,n){FOR(j,1,n)printf("%d ",g[i][j]);puts("");}
	return 0;
}

还可以维护传递闭包。

FOR(k,1,n) FOR(i,1,n) FOR(j,1,n) g[i][j]|=(g[i][k]&&g[k][j]);

16.kruskal

const int N=2e5+10;
int n,m,fa[N],tot;
struct node{int from,to,w;}edge[N];
void add(int x,int y,int w){edge[++tot]={x,y,w};}
bool cmp(node a,node b){return a.w<b.w;}

namespace DSU{
	int find(int x){if(x!=fa[x])fa[x]=find(fa[x]);return fa[x];}
	void merge(int x,int y){if(find(x)==find(y))return;fa[find(x)]=find(y);}
}
using namespace DSU;

int main(){
	n=rd,m=rd;FOR(i,1,n) fa[i]=i;
	FOR(i,1,m){int x=rd,y=rd,w=rd;add(x,y,w);}
	sort(edge+1,edge+1+m,cmp);
	int cnt=0,res=0;
	FOR(i,1,m){
		int x=DSU::find(edge[i].from),y=DSU::find(edge[i].to),w=edge[i].w;
		if(x==y) continue;
		fa[x]=y,res+=w,cnt++;
	}
	if(cnt<n-1) puts("orz");
	else printf("%d\n",res);
	return 0;
}

17.差分约束(spfa 判负环)

const int N=10010;
int n,m,head[N],tot,cnt[N],dist[N],vis[N];
struct node{int to,nxt,w;}edge[N<<1];
void add(int x,int y,int w){edge[++tot]={y,head[x],w},head[x]=tot;}
bool spfa(int s){
	memset(vis,0,sizeof(vis)),memset(dist,0x3f,sizeof(dist));
	queue<int> q;q.push(s),dist[s]=0,vis[s]=1;
	while(!q.empty()){
		int t=q.front();q.pop(),vis[t]=0;
		for(int i=head[t];i;i=edge[i].nxt){
			int y=edge[i].to;
			if(dist[y]>dist[t]+edge[i].w){
				dist[y]=dist[t]+edge[i].w,cnt[y]=cnt[t]+1;
				if(cnt[y]>n) return true;
				if(!vis[y]) vis[y]=1,q.push(y);
			}
		}
	}
	return false;
}
int main(){
	n=rd,m=rd;
	FOR(i,1,m){int x=rd,y=rd,w=rd;add(y,x,w);}
	FOR(i,1,n) add(0,i,0);
	if(spfa(0)) puts("NO");
	else{
		FOR(i,1,n) printf("%d ",dist[i]);
	}
	return 0;
}

18.Trie 维护字符串

const int N=3e6+10;
int T,n,q,tr[N][66],cnt[N],idx;char ch[N];

namespace Trie{
	int cal(char ch){
		if(ch>='a'&&ch<='z') return ch-'a';
		else if(ch>='A'&&ch<='Z') return ch-'A'+26;
		return ch-'0'+52;
	}
	void insert(char a[]){
		int p=0,len=strlen(a+1);
		FOR(i,1,len){
			int t=cal(a[i]);
			if(!tr[p][t]) tr[p][t]=++idx;
			p=tr[p][t],cnt[p]++;
		}
	}
	int query(char a[]){
		int p=0,len=strlen(a+1);
		FOR(i,1,len){
			int t=cal(a[i]);
			if(!tr[p][t]) return 0;
			p=tr[p][t];
		}
		return cnt[p];
	}
}
using namespace Trie;

void solve(){
	FOR(i,0,idx) FOR(j,0,65) tr[i][j]=0;
	FOR(i,0,idx) cnt[i]=0;
	idx=0,n=rd,q=rd;
	FOR(i,1,n) scanf("%s",ch+1),Trie::insert(ch);
	while(q--){
		scanf("%s",ch+1);
		printf("%d\n",Trie::query(ch));
	}
}
int main(){
	T=rd;
	while(T--) solve();
	return 0;
}

19.01 Trie

const int N=1e5+10;
int n,dis[N],head[N],tot,ans,idx;
struct trie{int son[2];}tr[N*32];
struct node{int to,nxt,w;}edge[N<<1];
void add(int x,int y,int w){edge[++tot]={y,head[x],w},head[x]=tot;}
void dfs(int x,int fa){
	for(int i=head[x];i;i=edge[i].nxt){
		int y=edge[i].to;if(y==fa) continue;
		dis[y]=dis[x]^edge[i].w,dfs(y,x);
	}
}

namespace Trie{
	void insert(int x){
		int p=0;
		ROF(i,31,0){
			int c=(x>>i)&1;
			if(!tr[p].son[c]) tr[p].son[c]=++idx;
			p=tr[p].son[c];
		}
	}
	int query(int x){
		int p=0,res=0;
		ROF(i,31,0){
			int c=(x>>i)&1;
			if(tr[p].son[c^1]) res^=(1<<i),p=tr[p].son[c^1];
			else p=tr[p].son[c];
		}
		return res;
	}
}
using namespace Trie;

int main(){
	n=rd;FOR(i,1,n-1){int x=rd,y=rd,w=rd;add(x,y,w),add(y,x,w);}
	dfs(1,0);
	FOR(i,1,n) Trie::insert(dis[i]);
	FOR(i,1,n) ans=max(ans,Trie::query(dis[i]));
	printf("%d\n",ans);
	return 0;
}

20.tarjan 缩点+拓扑排序 dp

非常典。

const int N=1e5+10;
int n,m,head[N],tot,dfn[N],low[N],tim,stk[N],top,vis[N],cnt,scc[N],w[N],dis[N],a[N],deg[N];
vector<int> e[N];
struct node{int to,nxt;}edge[N];
il void add(int x,int y){edge[++tot]={y,head[x]},head[x]=tot;}
void tarjan(int x){
	dfn[x]=low[x]=++tim,stk[++top]=x,vis[x]=1;
	for(auto y:e[x]){
		if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
		else if(vis[y]) low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		int y;cnt++;do{
			y=stk[top--],scc[y]=cnt,w[cnt]+=a[y],vis[y]=0;
		}while(x!=y);
	}
}
void toposort(){
	int ans=0;queue<int> q;
	FOR(i,1,cnt) if(!deg[i]) q.push(i),dis[i]=w[i];
	while(!q.empty()){
		int t=q.front();q.pop();
		for(int i=head[t];i;i=edge[i].nxt){
			int y=edge[i].to;
			dis[y]=max(dis[y],dis[t]+w[y]);
			if(!--deg[y]) q.push(y);
		}
	}
	FOR(i,1,cnt) ans=max(ans,dis[i]);
	printf("%d\n",ans);
}
int main(){
	n=rd,m=rd;FOR(i,1,n) a[i]=rd;
	FOR(i,1,m){int x=rd,y=rd;e[x].pb(y);}
	FOR(i,1,n) if(!dfn[i]) tarjan(i);
	FOR(x,1,n) for(auto y:e[x]) if(scc[x]!=scc[y]) add(scc[x],scc[y]),deg[scc[y]]++;
	toposort(); 
	return 0;
}

21.点双

void tarjan(int x){
	dfn[x]=low[x]=++tim,stk[++top]=x;
	if(!head[x]){v[++cnt].pb(x);return;}
	for(int i=head[x];i;i=edge[i].nxt){
		int y=edge[i].to;
		if(!dfn[y]){
			tarjan(y),low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x]){
				int z;cnt++;do{
					z=stk[top--],v[cnt].pb(z);
				}while(z!=y);
				v[cnt].pb(x);
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
}

22.边双

void tarjan(int x,int in_edge){
	dfn[x]=low[x]=++tim,stk[++top]=x,vis[x]=1;
	for(int i=head[x];i;i=edge[i].nxt){
		int y=edge[i].to;
		if(!dfn[y]) tarjan(y,i),low[x]=min(low[x],low[y]);
		else if(i!=(in_edge^1)) low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		int y;cnt++;do{
			y=stk[top--],vis[y]=0,v[cnt].pb(y);
		}while(x!=y);
	}
}

23.扫描线求矩形面积并

扫描线的思想真的很常用。

const int N=2e5+10;
int n,lsh[N],tot,len[N<<2],tag[N<<2];
struct node{int x,y1,y2,k;}seg[N];
bool cmp(node a,node b){return a.x<b.x;}

namespace SMT{
	#define mid ((l+r)>>1)
	#define ls (u<<1)
	#define rs (u<<1|1)
	void pushup(int u,int l,int r){
		if(tag[u]) len[u]=lsh[r+1]-lsh[l];
		else if(l!=r) len[u]=len[ls]+len[rs];
		else len[u]=0;
	}
	void modify(int u,int l,int r,int ql,int qr,int v){
		if(ql<=l&&r<=qr){tag[u]+=v;pushup(u,l,r);return;}
		if(ql<=mid) modify(ls,l,mid,ql,qr,v);
		if(qr>mid) modify(rs,mid+1,r,ql,qr,v);
		pushup(u,l,r);
	}
	#undef mid
	#undef ls
	#undef rs
}
using namespace SMT;

int main(){
	n=rd;
	FOR(i,1,n){
		int x1=rd,y1=rd,x2=rd,y2=rd;
		seg[i]={x1,y1,y2,1},seg[i+n]={x2,y1,y2,-1};
		lsh[i]=y1,lsh[i+n]=y2;
	}
	sort(lsh+1,lsh+1+2*n),tot=unique(lsh+1,lsh+1+2*n)-lsh-1;
	sort(seg+1,seg+1+2*n,cmp);ll ans=0;
	FOR(i,1,2*n){
		if(i>1) ans+=1ll*len[1]*(seg[i].x-seg[i-1].x);
		int l=lower_bound(lsh+1,lsh+1+tot,seg[i].y1)-lsh;
		int r=lower_bound(lsh+1,lsh+1+tot,seg[i].y2)-lsh;
		SMT::modify(1,1,tot,l,r-1,seg[i].k);
	}
	printf("%lld\n",ans);
	return 0;
}

24.欧拉路径

const int N=2e5+10;
int n,m,cnt[2],deg[N][2],st=1,nxt[N],stk[N],top;vector<int> e[N];
void dfs(int x){
	for(int i=nxt[x];i<U(e[x]);i=nxt[x]){
		nxt[x]=i+1;
		dfs(e[x][i]);
	}
	stk[++top]=x;
}
int main(){
	n=rd,m=rd;
	FOR(i,1,m){int x=rd,y=rd;e[x].pb(y),deg[x][0]++,deg[y][1]++;}
	FOR(i,1,n) sort(e[i].begin(),e[i].end());
	bool flag=true;
	FOR(i,1,n){
		if(deg[i][0]!=deg[i][1]){
			flag=false;
			if(deg[i][0]-deg[i][1]==1) st=i,cnt[0]++;
			else if(deg[i][1]-deg[i][0]==1) cnt[1]++;
			else{puts("No");return 0;}
		}
	}
	if(!flag&&cnt[0]!=1&&cnt[1]!=1){puts("No");return 0;}
	dfs(st);
	ROF(i,top,1) printf("%d ",stk[i]);
	return 0;
}

标签:cnt,return,int,模版,汇总,tr,rd,edge
From: https://www.cnblogs.com/summ1t/p/18573434

相关文章

  • 数据结构(汇总)
    1.1.1基本概念数据:数据是信息的载体,是描述客观事物属性的字、字符及所有能输入到计算机并且被计算机程序识别和处理的符号的集合。(数据是计算机程序加工的原料)数据元素、数据项:数据元素是数据的基本单位,一个数据元素可由若干个数据项组成,数据项是构成数据元素的不可分割的......
  • NocoBase 本周更新汇总:优化 REST API 数据源插件
    汇总一周产品更新日志,最新发布可以前往我们的博客查看。NocoBase目前更新包括的版本更新包括三个分支:main,next和develop。main:截止目前最稳定的版本,推荐安装此版本。next:包含即将发布的新功能,经过初步测试的版本,可能存在部分已知或未知问题。主要面向测试用户,用于收集反......
  • java 基础知识汇总(1)
    目录1.什么是面向对象?1.1面向对象的特征1.1.1封装(Encapsulation):1.1.2继承(Inheritance):1.1.3多态(Polymorphism):1.1.4抽象(Abstraction):1.2面向对象与面向过程的区别1.3重载(Overload)与重写(Override)的区别   1.3.1重写(Override)1.3.2重载(Overload)1.4构造......
  • ASP.NET Core面试题汇总
    1.如何在controller中注入service?在configservices方法中配置这个service。在controller的构造函数中,添加这个依赖注入。 2.ASP.NETCore比ASP.NET更具优势的地方是什么?跨平台,ASP.NETCore可以运行在Windows、Linux和MAC系统上;对框架本安装没有依赖,所有依赖都跟......
  • 多模态融合:顶级一区idea,创新思路汇总
    2024深度学习发论文&模型涨点之——多模态融合多模态融合(MultimodalFusion)是指结合来自不同模态(如视觉、听觉、文本等)的数据,以提升信息处理和理解能力的技术方法。多模态数据通常具有不同的物理性质和信息特征,通过融合这些多模态信息,可以获得更全面和准确的理解。这种融合过......
  • 【超详细】MDK工程模版
    MDK工程模版新建MDK工程文件夹采用分层的思想进行工程管理,目录结构如下:名称作用Drivers存放硬件相关的驱动文件Middlewares存放第三方中间文件Output存放工程输出的文件Projects存放MDK工程文件User存放HAL库用户配置文件、main.c、中断处理文件以及分散的启动加载文件Do......
  • STM32和STM8开发工具、常用软件和开发环境汇总
    文章目录一、前言二、KeilC51软件三、KeilMDK-ARM四、STM32CubeMX及HAL库五、STM32CubeIDE六、STM8CubeMX七、STM32ST-LINKUtility一、前言整理一些常见的STM32/STM8开发所需要的安装包和工具。可以分别去官网下载最新的安装包。也可以通过关注【小康师兄】......
  • DSPf28335 --工程模版相关文件
    创建工程需要的两个文件DSP2833x_common1.cmd下图中的两个文件(由TI公司提供的)1、28335_RAM_lnk.cmd:程序下载到RAM中进行调试和仿真所使用的启动文件。2、F28335.cmd:程序下载到Flash中运行所使用的启动文件。2.gel用来存放一些扩展语言,扩展CCS功能,方便调试,(通常不更改)......
  • Python处理时间汇总-与时区相关的处理
    获取当前东八区时间以及统一时区的时间比较#coding:utf-8importpytzimportdatetime#定义东八区时区cst_timezone=pytz.timezone('Asia/Shanghai')#获取东八区的当前时间defget_cst_nowtime():returndatetime.datetime.now(cst_timezone)#将时间对象......
  • 体验游浪潮,推动旅游业变革|报告汇总PDF洞察(附原数据表)
    原文链接: https://tecdat.cn/?p=38347休闲游自诞生起便聚焦于探索新鲜体验!人们期待邂逅热情好客的当地人,品尝独特美食,漫步于陌生景致,见证(甚至参与)当地文化传统,畅享原汁原味的异域风情。文末172份旅游行业研究报告最新趋势已分享在交流群,阅读原文进群和500+行业人士共同交流和成......