关于存图方式
查看原帖
关于存图方式
1020916
mcmahaoran楼主2025/1/22 11:55

rt,其他操作完全一致,但用 vector 存图,可以水过,但用链式前向星存图会 T

注意到两条记录的用时差了接近一倍,有点难以理解,有人能解释一下为什么吗……

这是用 vector 存图的代码:

#include<iostream>
#include<cstring>
#include<vector>
#define skip(x) x=anc[x][i]
#define rep for(int v:e[u])
#define handle if(v==f)continue;
#define down for(int i=20;i>=0;--i)
#define init anc[u][0]=f;d[u]=d[f]+1;
using namespace std;

const int N=1e5+5;
const int Z=1e5;

int n,m,cnt;
int d[N],maxx[N*60],ans[N],id[N*60];
int ls[N*60],rs[N*60],root[N];
int anc[N][25];
vector<int> e[N];

inline void dfsA(int u,int f){
	init;
	for(int i=1;i<=20;++i){
		anc[u][i]=anc[anc[u][i-1]][i-1];
	}
	rep{
		handle;
		dfsA(v,u);
	}
	return ;
}

inline int LCA(int x,int y){
	if(d[x]<d[y])swap(x,y);
	down{
		if(d[anc[x][i]]>=d[y]){
			skip(x);
		}
	}
	if(x==y)return x;
	down{
		if(anc[x][i]==anc[y][i])continue;
		skip(x),skip(y);
	}
	return anc[x][0];
}

inline void pushup(int u){
	maxx[u]=maxx[ls[u]]>=maxx[rs[u]]?maxx[ls[u]]:maxx[rs[u]];
	id[u]=maxx[ls[u]]>=maxx[rs[u]]?id[ls[u]]:id[rs[u]];
	return ;
}

inline void update(int &u/*当前结点号*/,int l/*左端点*/,int r/*右端点*/,int x/*目标*/,int v/*1 或 -1*/){
	if(u==0)u=++cnt;
	if(l==r){
		maxx[u]+=v;
		id[u]=x;
		return ;
	}
	int mid=(l+r)/2;
	if(x<=mid)update(ls[u],l,mid,x,v);
	else update(rs[u],mid+1,r,x,v);
	pushup(u);
	return ;
}

inline int merge(int u,int v,int l,int r){
	if(u==0||v==0)return u==0?v:u;
	if(l==r){
		maxx[u]+=maxx[v];
		id[u]=l;
		return u;
	}
	int mid=(l+r)/2;
	ls[u]=merge(ls[u],ls[v],l,mid);
	rs[u]=merge(rs[u],rs[v],mid+1,r);
	pushup(u);
	return u;
}

inline void dfsB(int u,int f){
	rep{
		handle;
		dfsB(v,u);
		root[u]=merge(root[u],root[v],1,Z);
	}
	ans[u]=maxx[root[u]]?id[root[u]]:0;
	return ;
}

signed main(){
	cin>>n>>m;
	for(int i=1;i<n;++i){
		int a,b;
		cin>>a>>b;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	dfsA(1,0);
	for(int i=1;i<=m;++i){
		int x,y,z;
		cin>>x>>y>>z;
		int lca=LCA(x,y);
		update(root[x],1,Z,z,1);
		update(root[y],1,Z,z,1);
		update(root[lca],1,Z,z,-1);
		if(anc[lca][0])update(root[anc[lca][0]],1,Z,z,-1);
	}
	dfsB(1,0);
	for(int i=1;i<=n;++i)cout<<ans[i]<<"\n";
	return 0;
}

而这是用链式前向星存图的代码(甚至还卡了常:

#include<cstdio>
#define skip(x) x=anc[x][i]
#define rep for(int i=head[u];i;i=e[i].nxt)
#define handle int v=e[i].v;if(v==f)continue;
#define down for(int i=20;i>=0;--i)
#define init anc[u][0]=f;d[u]=d[f]+1;
using namespace std;

namespace OIfast{
	
	inline int read(){
		int n=0,f=1;
		char c=getchar();
		while(c<'0'||c>'9'){
			if(c=='-')f=-1;
			c=getchar();
		}
		while(c>='0'&&c<='9')n=n*10+c-'0',c=getchar();
		return n*f;
	}
	
	inline void print(int n){
		if(n<0)n=-n,putchar('-');
		if(n>=10)print(n/10);
		putchar(n%10+'0');
		return ;
	}
	
	inline void write(int n,char c){
		print(n),putchar(c);
		return ;
	}
	
}using namespace OIfast;

const int N=1e5+5;
const int Z=1e5;

int n,m,cnt,tot;
int head[N],d[N],maxx[N*60],ans[N],id[N*60];
int ls[N*60],rs[N*60],root[N];
int anc[N][25];

struct edge{
	int v,nxt;
}e[N];

inline void add(int u,int v){
	e[++cnt].v=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
	return ;
}

inline void dfsA(int u,int f){
	init;
	for(int i=1;i<=20;++i){
		anc[u][i]=anc[anc[u][i-1]][i-1];
	}
	rep{
		handle;
		dfsA(v,u);
	}
	return ;
}

inline int LCA(int x,int y){
	if(d[x]<d[y])x^=y,y^=x,x^=y;
	down{
		if(d[anc[x][i]]>=d[y]){
			skip(x);
		}
	}
	if(x==y)return x;
	down{
		if(anc[x][i]==anc[y][i])continue;
		skip(x),skip(y);
	}
	return anc[x][0];
}

inline void pushup(int u){
	maxx[u]=maxx[ls[u]]>=maxx[rs[u]]?maxx[ls[u]]:maxx[rs[u]];
	id[u]=maxx[ls[u]]>=maxx[rs[u]]?id[ls[u]]:id[rs[u]];
	return ;
}

inline void update(int &u/*当前结点号*/,int l/*左端点*/,int r/*右端点*/,int x/*目标*/,int v/*1 或 -1*/){
	if(u==0)u=++cnt;
	if(l==r){
		maxx[u]+=v;
		id[u]=x;
		return ;
	}
	int mid=(l+r)/2;
	if(x<=mid)update(ls[u],l,mid,x,v);
	else update(rs[u],mid+1,r,x,v);
	pushup(u);
	return ;
}

inline int merge(int u,int v,int l,int r){
	if(u==0||v==0)return u==0?v:u;
	if(l==r){
		maxx[u]+=maxx[v];
		id[u]=l;
		return u;
	}
	int mid=(l+r)/2;
	ls[u]=merge(ls[u],ls[v],l,mid);
	rs[u]=merge(rs[u],rs[v],mid+1,r);
	pushup(u);
	return u;
}

inline void dfsB(int u,int f){
	rep{
		handle;
		dfsB(v,u);
		root[u]=merge(root[u],root[v],1,Z);
	}
	ans[u]=maxx[root[u]]?id[root[u]]:0;
	return ;
}

signed main(){
	n=read(),m=read();
	for(int i=1;i<n;++i){
		int a=read(),b=read();
		add(a,b);
		add(b,a);
	}
	dfsA(1,0);
	for(int i=1;i<=m;++i){
		int x=read(),y=read(),z=read();
		int lca=LCA(x,y);
		update(root[x],1,Z,z,1);
		update(root[y],1,Z,z,1);
		update(root[lca],1,Z,z,-1);
		if(anc[lca][0])update(root[anc[lca][0]],1,Z,z,-1);
	}
	dfsB(1,0);
	for(int i=1;i<=n;++i)write(ans[i],'\n');
	return 0;
}
2025/1/22 11:55
加载中...