线段树合并样例不过求调
查看原帖
线段树合并样例不过求调
1308728
xsmfollower楼主2025/2/2 11:49

请忽略代码中所有调试语句。

#include<iostream>
#include<vector>
using namespace std;
const int N=1e5+10,M=2e6+10; vector<int>g[N]; int tot,rt[N],col[N]; long long ans[N];
struct SGT { int lc,rc,cnt; long long ans; }tree[M];
void pushup(int u) {
	if(tree[tree[u].lc].cnt>tree[tree[u].rc].cnt) tree[u].cnt=tree[tree[u].lc].cnt,tree[u].ans=tree[tree[u].lc].ans;
	if(tree[tree[u].lc].cnt<tree[tree[u].rc].cnt) tree[u].cnt=tree[tree[u].rc].cnt,tree[u].ans=tree[tree[u].rc].ans;
	if(tree[tree[u].lc].cnt==tree[tree[u].rc].cnt) tree[u].cnt=tree[tree[u].lc].cnt,tree[u].ans=tree[tree[u].lc].ans+tree[tree[u].rc].ans;
}
void update(int &u,int l,int r,int x) {
  	if(!u) u=++tot;
  	if(l==r) return tree[u].cnt++,tree[u].ans=l,void();
  	int m=(l+r)>>1;
  	if(x<=m) update(tree[u].lc,l,m,x);
  	else update(tree[u].rc,m+1,r,x);
  	pushup(u);
}
int mer(int rt1,int rt2,int l,int r) {
	if(!rt1||!rt2) return rt1+rt2;
	if(l==r) return cout<<l<<'\n',tree[rt1].cnt+=tree[rt2].cnt,tree[rt1].ans=l,rt1;
	int mid=(l+r)>>1;
	tree[rt1].lc=mer(tree[rt1].lc,tree[rt2].lc,l,mid);
	tree[rt1].rc=mer(tree[rt1].rc,tree[rt2].rc,mid+1,r);
	return pushup(rt1),rt1;
}
void dfs(int u,int fa) {
	for(auto v:g[u]) if(v!=fa) dfs(v,u),rt[u]=mer(rt[u],rt[v],1,N);
	update(rt[u],1,N,col[u]),ans[rt[u]]=tree[rt[u]].ans;
	cout<<u<<' '<<rt[u]<<' '<<tree[rt[u]].ans<<'\n';
	for(int i=1;i<=16;i++) cout<<tree[i].cnt<<' '<<tree[i].ans<<'\n';
}
int main() {
	ios::sync_with_stdio(false),cin.tie(nullptr);
	int n; cin>>n;
	for(int i=1;i<=n;i++) cin>>col[i],rt[i]=i;
	for(int i=1,u,v;i<n;i++) cin>>u>>v,g[u].push_back(v),g[v].push_back(u);
	dfs(1,0);
	for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
	return 0;
}
2025/2/2 11:49
加载中...