Luogu4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
https://www.luogu.com.cn/problem/P4556
线段树合并
线段树合并即合并两颗权值线段树,合并方法非常简单
但是这道题我调了很久
原因:数组开小了QAQ
线段树合并一般数组开\(n \log n\)级别,然后根据操作次数乘上常数(更大也无伤大雅)
我\(ls\),\(rs\)数组开小了,导致玄学错误,结果晕头转向,最后才发现数组开小了
\(C++\)数组开小很多情况下不报错,因为它去调用其他数组的无用空间了,以至于难以发现错误
下次看到难以理解的错误(比如输出值在更改一个无关紧要的语句后不恒定),一定要去看数组(一个数组一个数组看过来)!
同时,可以将相同种类的数组放在一起
放代码吧。。。
\(Code:\)
#include<bits/stdc++.h>
#define N 200005
#define S 100000
#define pr pair<int,int>
using namespace std;
int n,m,x,y;
int cnt,tot,head[N],nxt[N],d[N],ac[N],lca[N],F[N],rt[N],ans[N];
int ls[N*25],rs[N*25],tree[N*25],id[N*25];
bool leaf[N*25];
vector<pr>q[N];
struct node
{
int x,y,z;
}e[N];
void add(int x,int y)
{
tot++;
d[tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int getf(int x)
{
if (ac[x]==x)
return x;
return ac[x]=getf(ac[x]);
}
void tarjan(int u,int f)
{
ac[u]=u;
for (int i=head[u];i;i=nxt[i])
{
int v=d[i];
if (v==f)
continue;
tarjan(v,u);
ac[v]=u;
F[v]=u;
}
for (vector<pr>::iterator it=q[u].begin();it!=q[u].end();it++)
if (ac[it->first])
lca[it->second]=getf(ac[it->first]);
}
void change(int &p,int l,int r,int x,int z)
{
if (!p)
p=++cnt;
if (l==r)
{
tree[p]+=z;
id[p]=l;
leaf[p]=true;
return;
}
int mid=(l+r) >> 1;
if (x<=mid)
change(ls[p],l,mid,x,z); else
change(rs[p],mid+1,r,x,z);
if (tree[ls[p]]>tree[rs[p]]||tree[ls[p]]==tree[rs[p]]&&id[ls[p]]<id[rs[p]])
{
tree[p]=tree[ls[p]];
id[p]=id[ls[p]];
} else
{
tree[p]=tree[rs[p]];
id[p]=id[rs[p]];
}
}
int merge(int x,int y)
{
if (!x||!y)
return x|y;
if (leaf[x]&&leaf[y])
{
tree[x]+=tree[y];
return x;
}
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
if (tree[ls[x]]>tree[rs[x]]||tree[ls[x]]==tree[rs[x]]&&id[ls[x]]<id[rs[x]])
{
tree[x]=tree[ls[x]];
id[x]=id[ls[x]];
} else
{
tree[x]=tree[rs[x]];
id[x]=id[rs[x]];
}
return x;
}
void dfs(int u)
{
for (int i=head[u];i;i=nxt[i])
{
int v=d[i];
if (v==F[u])
continue;
dfs(v);
rt[u]=merge(rt[u],rt[v]);
}
ans[u]=id[rt[u]];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
q[e[i].x].push_back(make_pair(e[i].y,i));
q[e[i].y].push_back(make_pair(e[i].x,i));
}
tarjan(1,0);
for (int i=1;i<=m;i++)
{
change(rt[e[i].x],1,S,e[i].z,1);
change(rt[e[i].y],1,S,e[i].z,1);
change(rt[lca[i]],1,S,e[i].z,-1);
if (F[lca[i]])
change(rt[F[lca[i]]],1,S,e[i].z,-1);
}
dfs(1);
for (int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}