60分线段树合并,以及小数据生成器
查看原帖
60分线段树合并,以及小数据生成器
643820
WangLianda楼主2023/2/15 09:32

60分线段树合并代码,小数据对拍无误。

代码如下:

#include<iostream>
#include<vector>
using namespace std;
const int Z=100000;
int n,m;
vector<vector<int>> a;
int deep[100005],f[20][100005],*fa=f[0],size[100005];
int dfs1(int u) {
	size[u]=1;
	deep[u]=deep[fa[u]]+1;
	for(auto&v:a[u]) {
		if(v==fa[u]) continue;
		fa[v]=u;
		size[u]+=dfs1(v);
	}
	return size[u];
}
int LCA(int x,int y) {
	if(deep[x]<deep[y]) swap(x,y);
	for(int k=19;k>=0;k--)
		if(deep[f[k][x]]>=deep[y])
			x=f[k][x];
	if(x==y) return x;
	for(int k=19;k>=0;k--)
		if(f[k][x]^f[k][y])
			x=f[k][x],
			y=f[k][y];
	return fa[x];
}
struct node {
	int l,r;
	pair<int,int> v;//最大值权值,最大值的最小编号的相反数 
	int lc,rc;
}t[100010*55];//注意空间 
int cnt;
int newn(int u,bool flag) {//newnode
	int mid=t[u].l+t[u].r>>1;
	if(!flag)//左儿子 
		t[t[u].lc=++cnt]={t[u].l,mid,{0,-t[u].l},0,0};//最大值编号先为左端点 
	else
		t[t[u].rc=++cnt]={mid+1,t[u].r,{0,-mid-1},0,0};
	return cnt;
}
void push_up(int u) {
	if(t[u].lc) t[u].v=max(t[u].v,t[t[u].lc].v);
	if(t[u].rc) t[u].v=max(t[u].v,t[t[u].rc].v);
}
void push(int u,int p,int v) {
	if(t[u].l==t[u].r&&t[u].l==p) t[u].v.first+=v;
	else {
		int mid=t[u].l+t[u].r>>1;
		if(p<=mid)
			if(t[u].lc) push(t[u].lc,p,v);
			else push(newn(u,0),p,v);
		else 
			if(t[u].rc) push(t[u].rc,p,v);
			else push(newn(u,1),p,v);
		push_up(u);
	}
}
pair<int,int> find(int u,int l,int r) {
	if(l<=t[u].l&&t[u].r<=r)
		return t[u].v; 
	int mid=t[u].l+t[u].r>>1;
	pair<int,int> ans={-1e9,-1e9};
	if(l<=mid&&t[u].lc) 
		ans=max(ans,find(t[u].lc,l,r));
	if(mid<r&&t[u].rc)
		ans=max(ans,find(t[u].rc,l,r));
	return ans;
}
void merge(int u1,int u2) {
	//u1<-u2
	if(t[u1].lc&&t[u1].rc) {
		if(t[u2].lc) merge(t[u1].lc,t[u2].lc);
		if(t[u2].rc) merge(t[u1].rc,t[u2].rc);
	}
	else {
		if(t[u1].lc&&t[u2].lc) merge(t[u1].lc,t[u2].lc);
		if(!t[u1].lc) t[u1].lc=t[u2].lc;
		if(t[u1].rc&&t[u2].rc) merge(t[u1].rc,t[u2].rc);
		if(!t[u1].rc) t[u1].rc=t[u2].rc;
		if(!t[u1].lc&&!t[u1].rc) 
			t[u1].v.first+=t[u2].v.first;
	}
	push_up(u1);
}
int ans[100005];
void dfs2(int u) {
	for(auto&v:a[u])
		if(v^fa[u])
			dfs2(v),merge(u,v);
	ans[u]=-find(u,1,Z).second;
}
int main() {
	cin>>n>>m;
	a.resize(n+1);
	for(int i=1;i<n;i++) {
		int u,v;
		cin>>u>>v;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	dfs1(1);
//	for(int i=1;i<=n;i++)
//		cout<<fa[i]<<' ';
//	cout<<endl;
	for(int k=1;k<20;k++)
		for(int i=1;i<=n;i++)
			f[k][i]=f[k-1][f[k-1][i]];
	for(int i=1;i<=n;i++)//前n个节点必然是根节点 
		t[i]={1,Z,{0,0},0,0};		
	cnt=n;
	while(m--) {
		int x,y,z;
		cin>>x>>y>>z;
		int lca=LCA(x,y);
		push(x,z,1);
		push(y,z,1);
		push(lca,z,-1);
		if(fa[lca]) push(fa[lca],z,-1);
	}
	dfs2(1);
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<endl;
	return 0;
} 

附送数据生成:

#include<bits/stdc++.h>
using namespace std;
int cnt,fa[100015];
int find(int x){
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
int random(int x,int y) {
	return rand()%(y-x+1)+x;
}
const int n=10,m=10;
bool vis[m+1];
int main()
{
	srand(time(0));
	cout<<n<<' '<<m<<endl;
	for(int i=1;i<=n;i++)fa[i]=i;
	while(cnt<n-1){
		int x=rand()%n+1,y=rand()%n+1;
		int x1=find(x),y1=find(y);
		if(x1!=y1) fa[x1]=y1,cnt++,cout<<x<<" "<<y<<endl;
	}
	for(int i=1;i<=m;i++) 
		cout<<random(1,n)<<' '<<random(1,n)<<' '<<random(1,100000)<<endl;
	
}

(虽然z跑不满)

STO

2023/2/15 09:32
加载中...