我的启发式合并跑了 40s+
查看原帖
我的启发式合并跑了 40s+
578628
Undead2008楼主2023/10/16 10:50

如题,我用的是 O(nlog⁡2n)O(n\log^2n) 的启发式合并。

从第 99 个点开始就 TLE 了,自测跑了 40s+。

程序是能跑出来的,但是跑的特别慢。

求助大佬我的启发式合并是不是写假了。

#include"bits/stdc++.h"
using namespace std;
#pragma GCC optimize(2)
#define endl '\n'
const int maxn = 3e5+10;
const int lgn = 18;
int n,m,f[maxn][lgn+2],dep[maxn],ans[maxn];
int t[maxn];
multiset<int>s[3][maxn];
vector<int>e[maxn];
int to[3][maxn],dl[3][maxn];
vector<int>add[3][maxn],del[3][maxn];
int delta[3]={1,-1,0};
#define mi multiset<int>::iterator
int cnt;
void dsu(int id,int U,int V){
	//把 u 合并到 v 上
	int &u=to[id][U],&v=to[id][V];
	if(u==v)return;
	if(s[id][u].size()>s[id][v].size())swap(u,v),swap(U,V);
	for(mi it=s[id][u].begin();it!=s[id][u].end();it++)
		s[id][v].insert((*it)+dl[id][u]-dl[id][v]);
	u=v;
}
void dfs(int p,int Fa){
	dep[p]=dep[Fa]+1;
	for(int i=0;i<e[p].size();i++){
		int to=e[p][i];
		if(to==Fa)continue;
		dfs(to,p);
		f[to][0]=p;
	}
}
int Lca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int i=lgn;i>=0;i--)
		if(dep[f[u][i]]>=dep[v])
			u=f[u][i];
	if(u==v)return u;
	for(int i=lgn;i>=0;i--)
		if(f[u][i]!=f[v][i])
			u=f[u][i],v=f[v][i];
	return f[u][0];
}
void query(int id,int p,int Fa){
	for(int i=0;i<e[p].size();i++){
		int to=e[p][i];
		if(to==Fa)continue;
		query(id,to,p);
		dsu(id,to,p);
	}
	int pos=to[id][p];
	dl[id][pos]+=delta[id];
	for(int j=0;j<add[id][p].size();j++){
		int to=add[id][p][j]-dl[id][pos];
		s[id][pos].insert(to);
	} 
	for(int j=0;j<del[id][p].size();j++){
		int to=del[id][p][j]-dl[id][pos];
		if(s[id][pos].find(to)!=s[id][pos].end())
			s[id][pos].erase(s[id][pos].find(to));
	} 
	ans[p]+=s[id][pos].count(t[p]-dl[id][pos]);
}
int main(){
	//freopen("P1600_9.in","r",stdin);
	//freopen("ReTF.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1,u,v;i<n;i++){
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs(1,0);
	for(int j=1;j<=lgn;j++)
		for(int i=1;i<=n;i++)
			f[i][j]=f[f[i][j-1]][j-1];
	for(int i=1;i<=n;i++)
		cin>>t[i],to[0][i]=to[1][i]=i;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		int Lc=Lca(u,v),dis=dep[u]+dep[v]-dep[Lc]*2;
		add[0][u].push_back(0);
		if(Lc!=1)del[0][f[Lc][0]].push_back(dep[u]-dep[Lc]+1);
		add[1][v].push_back(dis);
		del[1][Lc].push_back(dep[u]-dep[Lc]);
	}
	query(0,1,0);
	query(1,1,0);
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
}
2023/10/16 10:50
加载中...