【题目描述】
有一个村庄在闹饥荒,善良而土豪的 TTL 决定给他们发放救济粮,该村庄有 n 户人家, 每两户人家之间只有一条路可以互相到达,即这些人家之间形成一棵树。现在 TTL 会以这 样的形式给他们发放粮食,选择两户人家,然后对这两个户人家路径上的所有人家都发放一 袋种类为 w 的救济粮。在完成一系列发放任务后, TTL 想知道每一户人家收到的粮食中数 量最多的是哪一种。
【输入】
第一行两个数 n, q,其中 n 表示村庄共有几户人家, q 表示 TTL 一共发放了几次粮食
接下来 n-1 行,每行两个数 x y,表示编号为 x 和 y 的两户人家之间连有边
接下来 q 行,每行三个数 x y w,表示 TTL 选择了 x 到 y 的路径,对每户人家发放 1 袋种类为 w 的粮食。
【输出】
输出 n 行,第 i 行输出编号为 i 的人家收到的粮食中数量最多的种类号,如果有多个数 量相同的粮食,输出其中最小的种类号,如果没有收到粮食,输出 0
【样例输入 】
2 4
1 2
1 1 1
1 2 2
2 2 2
2 2 1
【样例2输入】:
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
【样例输出】
1
2
【样例2输出】:
2
3
3
0
2
【思路】
首先呢,这道题正解显然是树链剖分。但是我太菜了,想不出正解,只能用些歪门邪道骗分,竟然还AC了。
我们可以对每一种路径修改的w进行排序,对每一种w分类处理。利用树上差分进行路径修改,每种颜色结束后深搜处理每个人家的粮食,并尝试更新答案。最后再卡卡常,输出即可。
代码:(也许用欧拉序求lca会快一点,但是这道题这个做法的的瓶颈在于w的数量,不在于lca,但是卡卡常倒不错 )
#include
#include
#include
#include
#include
#include
#include
#define re register
using namespace std;
int n,m,a,b,s,t;
const int N=2e5+1;
int f[N];
int nxp[N<<2|1];
int ans[N];
int id[N];
int cnt=0,tot=0;
struct ndeo{
int u,v;
}e[N];
inline void add(int &u,int &v)
{
e[++cnt].u=u;
e[cnt].v=v;
nxp[cnt]=f[u];
f[u]=cnt;
}
int fa[N][20];
int dep[N];
int lo[21]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072};
void dfs(int u)
{
for(int re i=1;lo[i]<=dep[u];i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int re i=f[u];i;i=nxp[i])
{
int v=e[i].v;
if(!dep[v])
{
dep[v]=dep[u]+1;
fa[v][0]=u;
dfs(v);
}
}
}
inline int lca(int a,int b)
{
if(dep[a]<dep[b])swap(a,b);
int t=dep[a]-dep[b];
for(int re i=0;lo[i]<=t;i++)
if(t&lo[i])a=fa[a][i];
if(a==b)return a;
for(int re i=17;i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
char p;
int now=0;
int sum[N];
int cf[N];
struct no{
int w;
int x,y;
}q[N];
inline bool cmp(no a,no b){return a.w<b.w;}
inline int red()
{
int data=0;char ch=0;
ch=getchar();
while((ch<'0' || ch>'9')) ch=getchar();//假读入优化,这里应该判负,但是为了卡常,下面输出优化亦然。
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data;
}
int Dfs(int u)
{
for(int re i=f[u];i;i=nxp[i])
{
int v=e[i].v;
if(dep[v]==dep[u]+1)
{
cf[u]+=Dfs(v);
}
}
if(cf[u]>ans[u])
{
ans[u]=cf[u];
id[u]=now;
}
return cf[u];
}
void print(int x)
{
if(x>9)
print(x / 10);
putchar(x % 10 + '0');
return;
}
int main()
{
n=red();m=red();
for(int re i=1;i<n;i++)
{
a=red();b=red();
add(a,b);add(b,a);
}
dep[1]=1;
dfs(1);
for(int re i=1;i<=m;i++)
{
q[i].x=red();
q[i].y=red();
q[i].w=red();
}
sort(q+1,q+m+1,cmp);
now=q[1].w;
for(int re i=1;i<=m;i++)
{
if(now!=q[i].w)
{
Dfs(1);
memset(cf,0,sizeof(cf));
now=q[i].w;
}
a=q[i].x,b=q[i].y;
int lc=lca(a,b);
cf[a]++;
cf[b]++;
cf[lc]--;
if(lc!=1)
cf[fa[lc][0]]--;
}
Dfs(1);
for(int re i=1;i<=n;i++)
print(id[i]),putchar('\n');
}