题面
路径(u,v)修改
根据套路可以变成u、v处+1,lca(u,v)处-1
单点查询变为子树查询
然后搜题解
发现可以每个点开以颜色为权值 的权值线段树
统计子树信息就是线段树合并
根据某种理论
叶子结点个数一定时
复杂度就是一个log的
(刚学的)
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;
const int N=200200,oo=1e9;
void read(int &hy)
{
hy=0;
char cc=getchar();
while(cc<'0'||cc>'9')
cc=getchar();
while(cc>='0'&&cc<='9')
{
hy=(hy<<3)+(hy<<1)+cc-'0';
cc=getchar();
}
}
int n,m,ans[N];
int head[N],nex[N],to[N],cnt;
int fa[N][20],tim[N],times;
int cur,rm[N];
map<int ,int> mp;
struct yy
{
int l,r,x;
}t[10001000];
int root[N];
void add(int u,int v)
{
to[++cnt]=v;
nex[cnt]=head[u];
head[u]=cnt;
}
void dfs(int x)
{
tim[x]=++times;
for(int h=head[x];h;h=nex[h])
if(to[h]!=fa[x][0])
{
fa[to[h]][0]=x;
dfs(to[h]);
}
}
int lca(int x,int y)
{
if(x==y)
return x;
if(tim[x]>tim[y])
swap(x,y);
for(int j=19;j>=0;j--)
if(tim[fa[y][j]]>tim[x])
y=fa[y][j];
return fa[y][0];
}
void update(int &ro,int l,int r,int p,int q)
{
if(!ro)
ro=++cnt;
if(l==r)
{
t[ro].x+=q;
return;
}
int mid=(l+r)/2;
if(p<=mid)
update(t[ro].l,l,mid,p,q);
else
update(t[ro].r,mid+1,r,p,q);
t[ro].x=max(t[t[ro].l].x,t[t[ro].r].x);
}
int find(int ro,int l,int r)
{
if(!t[ro].x)
return 0;
if(l==r)
return l;
int mid=(l+r)/2;
if(t[t[ro].l].x==t[ro].x)
return find(t[ro].l,l,mid);
else
return find(t[ro].r,mid+1,r);
}
void unite(int a,int b,int l,int r)
{
if(l==r)
{
t[a].x+=t[b].x;
return;
}
int mid=(l+r)/2;
if(t[b].l)
if(!t[a].l)
t[a].l=t[b].l;
else
unite(t[a].l,t[b].l,l,mid);
if(t[b].r)
if(!t[a].r)
t[a].r=t[b].r;
else
unite(t[a].r,t[b].r,mid+1,r);
t[a].x=max(t[t[a].l].x,t[t[a].r].x);
}
void work(int x)
{
for(int h=head[x];h;h=nex[h])
if(to[h]!=fa[x][0])
{
work(to[h]);
unite(root[x],root[to[h]],1,100000);
}
ans[x]=find(root[x],1,100000);
}
int main()
{
cin>>n>>m;
for(int i=1;iint u,v;
read(u);
read(v);
add(u,v);
add(v,u);
}
fa[1][0]=1;
dfs(1);
for(int j=1;j<=19;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
cnt=n;
for(int i=1;i<=n;i++)
root[i]=i;
while(m--)
{
int u,v,w;
read(u);
read(v);
read(w);
/* if(!mp.count(w))
{
mp[w]=++cur;
rm[cur]=w;
}
w=mp[w];*/
int lc=lca(u,v);
update(root[u],1,100000,w,1);
update(root[v],1,100000,w,1);
update(root[lc],1,100000,w,-1);
if(lc!=1)
update(root[fa[lc][0]],1,100000,w,-1);
}
work(1);
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}