发放粮食
描述
有一个村庄在闹饥荒,善良而土豪的YGH决定给他们发放救济粮,该村庄有 n 户人家,每两户人家之间只有一条路可以互相到达,即这些人家之间形成一棵树。现在 YGH 会以这样的形式给他们发放粮食,选择两户人家,然后对这两个户人家路径上的所有人家都发放一袋种类为 w 的救济粮。在完成一系列发放任务后,YGH 想知道每一户人家收到的粮食中数量最多的是哪一种。
输入
第一行两个数 n,q,其中 n 表示村庄共有几户人家,q 表示 YGH 一共发放了几次粮食。接下来 n-1 行,每行两个数 x y,表示编号为 x 和 y 的两户人家之间连有边。接下来 q 行,每行三个数 x y w,表示 YGH 选择了 x 到 y 的路径,对每户人家发放 1 袋种类为 w 的粮食。
输出
输出 n 行,第 i 行输出编号为 i 的人家收到的粮食中数量最多的种类号,如果有多个数量相同的粮食,输出其中最小的种类号,如果没有收到粮食,输出0
样例输入
[1]
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]
1
2
[2]
2
3
3
0
2
提示
对于 40% 的数据 n<=1000,q<=1000,1<=w<=1000
描述
有一个村庄在闹饥荒,善良而土豪的YGH决定给他们发放救济粮,该村庄有 n 户人家,每两户人家之间只有一条路可以互相到达,即这些人家之间形成一棵树。现在 YGH 会以这样的形式给他们发放粮食,选择两户人家,然后对这两个户人家路径上的所有人家都发放一袋种类为 w 的救济粮。在完成一系列发放任务后,YGH 想知道每一户人家收到的粮食中数量最多的是哪一种。
输入
第一行两个数 n,q,其中 n 表示村庄共有几户人家,q 表示 YGH 一共发放了几次粮食。接下来 n-1 行,每行两个数 x y,表示编号为 x 和 y 的两户人家之间连有边。接下来 q 行,每行三个数 x y w,表示 YGH 选择了 x 到 y 的路径,对每户人家发放 1 袋种类为 w 的粮食。
输出
输出 n 行,第 i 行输出编号为 i 的人家收到的粮食中数量最多的种类号,如果有多个数量相同的粮食,输出其中最小的种类号,如果没有收到粮食,输出0
样例输入
[1]
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]
1
2
[2]
2
3
3
0
2
提示
对于 40% 的数据 n<=1000,q<=1000,1<=w<=1000
对于 100% 的数据 n<=100000,q<=100000,1<=w<=100000 1<=x,y<=n
这道题我们可以用树链剖分搞它,也可以将每个点建立一个线段树。但如果见那么多线段树就会MLE就GG了,所以我们用启发式合并来优化,但还是不够,所以我们再节约点内存用个队列。
作为一个高一的菜鸟就不把我的暴力程序给出来了,附某大大的代码
#include <cstdio>
#include <cstring>
#include <vector>
#define lson rt<<1
#define rson rt<<1|1
#define maxn 100010
using namespace std;
struct Pair {
int ind, val;
Pair(){}
Pair( int ii, int vv ) : ind(ii), val(vv) {}
};
int n, q;
vector<int> g[maxn], flag[maxn];
int siz[maxn], son[maxn], dep[maxn], pre[maxn], top[maxn], vid[maxn], id_clock;
int maxw, ans[maxn];
Pair seg[maxn<<2];
void input() {
scanf( "%d%d", &n, &q );
for( int i=1,u,v; i<n; i++ ) {
scanf( "%d%d", &u, &v );
g[u].push_back(v);
g[v].push_back(u);
}
}
void update( int w, int delta, int rt, int l, int r ) {
if( l==r ) {
seg[rt].val += delta;
seg[rt].ind = l;
return;
}
int mid = (l+r)>>1;
if( mid>=w ) update( w, delta, lson, l, mid );
else update( w, delta, rson, mid+1, r );
seg[rt] = seg[lson].val < seg[rson].val ? seg[rson] : seg[lson];
}
void dfs1( int u ) {
siz[u] = 1, son[u] = 0;
for( int t=0; t<(int)g[u].size(); t++ ) {
int v=g[u][t];
if( v==pre[u] ) continue;
dep[v] = dep[u]+1;
pre[v] = u;
dfs1(v);
siz[u] += siz[v];
son[u] = siz[v]>siz[son[u]] ? v : son[u];
}
}
void dfs2( int u, int tp ) {
top[u] = tp, vid[u] = ++id_clock;
if( son[u] ) dfs2( son[u], tp );
for( int t=0; t<(int)g[u].size(); t++ ) {
int v=g[u][t];
if( v==pre[u] || v==son[u] ) continue;
dfs2( v, v );
}
}
void build() {
dep[1] = pre[1] = 1;
dfs1(1);
id_clock = 0;
dfs2(1,1);
}
void modify( int u, int v, int w ) {
while( top[u] != top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
flag[vid[top[u]]].push_back(w);
flag[vid[u]+1].push_back(-w);
u = pre[top[u]];
}
if( dep[u]<dep[v] ) swap(u,v);
flag[vid[v]].push_back(w);
flag[vid[u]+1].push_back(-w);
}
void answer() {
for( int i=1; i<=q; i++ ) {
int u, v, w;
scanf( "%d%d%d", &u, &v, &w );
modify( u, v, w );
maxw = max( maxw, w );
}
for( int i=1; i<=id_clock; i++ ) {
for( int t=0; t<(int)flag[i].size(); t++ ) {
if( flag[i][t]>0 ) update( flag[i][t], 1, 1, 1, maxw );
if( flag[i][t]<0 ) update( -flag[i][t], -1, 1, 1, maxw );
}
if( seg[1].val==0 ) ans[i] = 0;
else ans[i] = seg[1].ind;
}
for( int i=1; i<=n; i++ )
printf( "%d\n", ans[vid[i]] );
}
int main() {
input();
build();
answer();
}
void pv( vector<int> &v ) {
for( int t=0; t<(int)v.size(); t++ )
fprintf( stderr, "%d ", v[t] );
fprintf( stderr, "\n" );
}