bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】
这居然是我第一次写线段树合并……所以我居然在合并的时候加点结果WAWAWAMLEMLEMLE……!ro的时候居然直接指到la就行……
树上差分,每个点建一棵动态开点线段树,然后统计答案的时候合并即可
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=100005;
int n,m,h[N],cnt,de[N],fa[N],si[N],hs[N],fr[N],c[N],rt[N],tot,ans[N],d[N];
struct qwe
{
int ne,to;
}e[N<<1];
struct xds
{
int ls,rs,mx,p;
}t[7500005];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(int u,int v)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
}
void dfs1(int u,int fat)
{
fa[u]=fat;
de[u]=de[fat]+1;
si[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fat)
{
dfs1(e[i].to,u);
d[u]++;
si[u]+=si[e[i].to];
if(si[e[i].to]>si[hs[u]])
hs[u]=e[i].to;
}
}
void dfs2(int u,int top)
{
fr[u]=top;
if(!hs[u])
return;
dfs2(hs[u],top);
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fa[u]&&e[i].to!=hs[u])
dfs2(e[i].to,e[i].to);
}
int lca(int u,int v)
{//cerr<<u<<" "<<v<<endl;
for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
return de[u]<de[v]?u:v;
}
void ud(int ro)
{
if(t[ro].ls&&t[t[ro].ls].mx>=t[t[ro].rs].mx)
t[ro].p=t[t[ro].ls].p,t[ro].mx=t[t[ro].ls].mx;
else
t[ro].p=t[t[ro].rs].p,t[ro].mx=t[t[ro].rs].mx;
}
void update(int &ro,int l,int r,int p,int v)
{
if(!ro)
ro=++tot,t[ro].p=l;
if(l==r)
{//cerr<<p<<" "<<v<<" "<<t[ro].mx<<endl;
t[ro].mx+=v;
return;
}
int mid=(l+r)>>1;
if(p<=mid)
update(t[ro].ls,l,mid,p,v);
else
update(t[ro].rs,mid+1,r,p,v);
ud(ro);
}
void hb(int &ro,int la,int l,int r)
{
if(!la)
return;
if(!ro)
{
ro=la;
return;
}
if(l==r)
{
t[ro].mx+=t[la].mx;
return;
}
int mid=(l+r)>>1;
hb(t[ro].ls,t[la].ls,l,mid);
hb(t[ro].rs,t[la].rs,mid+1,r);
ud(ro);
}
// void dfs(int u)
// {
// for(int i=h[u];i;i=e[i].ne)
// if(e[i].to!=fa[u])
// {
// dfs(e[i].to);
// hb(rt[u],rt[e[i].to],1,100000);
// }
// if(t[rt[u]].mx<=0)
// ans[u]=0;
// else
// ans[u]=t[rt[u]].p;//cerr<<u<<" "<<t[rt[u]].mx<<endl;
// }
int main()
{
n=read(),m=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y),add(y,x);
}
dfs1(1,0);
dfs2(1,1);
t[0].mx=-1e9;
while(m--)
{
int x=read(),y=read(),z=read(),lc=lca(x,y);
update(rt[x],1,100000,z,1);
update(rt[y],1,100000,z,1);
update(rt[lc],1,100000,z,-1);
if(fa[lc])
update(rt[fa[lc]],1,100000,z,-1);
// cerr<<t[rt[x]].p<<" "<<t[rt[x]].mx<<" "<<t[rt[y]].p<<" "<<t[rt[y]].mx<<" "<<t[rt[lc]].p<<" "<<t[rt[lc]].mx<<" "<<t[rt[fa[lc]]].p<<" "<<t[rt[fa[lc]]].mx<<" "<<endl;
}
// dfs(1);
queue<int>q;
for(int i=1;i<=n;i++)
if(!d[i])
q.push(i);
while(!q.empty())
{
int u=q.front();//cerr<<u<<endl;
q.pop();
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fa[u])
hb(rt[u],rt[e[i].to],1,100000);
if(t[rt[u]].mx<=0)
ans[u]=0;
else
ans[u]=t[rt[u]].p;
if(!(--d[fa[u]]))
q.push(fa[u]);
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}