acwing連線(bzoj3307)
深繪里一直很討厭雨天。
灼熱的天氣穿透了前半個夏天,後來一場大雨和隨之而來的洪水,澆滅了一切。
雖然深繪里家鄉的小村落對洪水有著頑固的抵抗力,但也倒了幾座老房子,幾棵老樹被連根拔起,以及田地裡的糧食被弄得一片狼藉。
無奈的深繪里和村民們只好等待救濟糧來維生。
不過救濟糧的發放方式很特別。
有 n 個點,形成乙個樹狀結構。
有 m 次發放操作,每次選擇兩個點 x,y,對 x 到 y 的路徑上(包括 x,y)的每個點發放一袋 z 型別的物品。
求完成所有發放操作後,每個點存放最多的是哪種型別的物品。
第一行兩個正整數n,m,含義如題目所示。
接下來n-1行,每行兩個數(a,b),表示(a,b)間有一條邊。
再接下來m行,每行三個數(x,y,z),含義如題目所示。
共n行,第i行乙個整數,表示第i座房屋裡存放的最多的是哪種救濟糧,如果有多種救濟糧存放次數一樣,輸出編號最小的。
如果某座房屋裡沒有救濟糧,則對應一行輸出0。
1≤n,m≤100000,
1≤z≤10^9
5 3
1 23 1
3 45 3
2 3 3
1 5 2
3 3 3
233
02
需要掌握 樹上lca 和 動態開點線段樹
思想 差分, 離散化
根據題意明顯是 區間操作, 對於樹, 那麼就是樹上差分 和 樹剖 了
對於 (x, y) 增加 z, 根據差分, 思考發現, ++val[x][z], ++val[y][z], --val[lca(x, y)][z], --val[lca(x, y)的父節點][z], 可以在樹上線性跑出 每個節點 z 的數量
而 z 異常的大, 1e9, 而 m 只有1e5, 明顯需要離散化, 降低 z 的範圍
就算如此 對於每個節點 跑出 每個z的數量也是 **的
我們就要想到 log 級別的方法, 那就線段樹了, 然而肯定會爆記憶體, 所以要動態開點
對於節點數, 4 * m * log2(z(離散化)), 每個節點佔 12位元組, 在加上亂七八糟的lca和存輸入的陣列, 記憶體也不會太緊張(你要是節點東西多了, 會爆, 還是有點卡記憶體的)
#include #define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define io ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef pairpii;
typedef pairpll;
typedef vectorvi;
typedef double db;
const int n = 1e5 + 5, m = 7e6 + 5;
int n, m, _, k;
int h[n], ne[n << 1], to[n << 1], tota;
int dep[n], f[n][20], t;
int x[n], y[n], z[n], tax[n], tot, ans[n];
void add(int u, int v)
void bfs(int s) }}
int lca(int x, int y)
struct node tr[m];
int node, rt[n];
void push_up(int root)
void update(int& root, int l, int r, int val, int d)
int mid = (l + r) >> 1;
if (mid >= val) update(tr[root].l, l, mid, val, d);
else update(tr[root].r, mid + 1, r, val, d);
push_up(root);
}int merge(int a, int b)
tr[a].l = merge(tr[a].l, tr[b].l);
tr[a].r = merge(tr[a].r, tr[b].r);
push_up(a);
return a;
}int query(int root, int l, int r)
void dfs(int u, int fa)
ans[u] = tax[query(rt[u], 1, tot)];
}int main()
bfs(1);
rep(i, 1, m) cin >> x[i] >> y[i] >> z[i], tax[i] = z[i];
sort(tax + 1, tax + 1 + m);
tot = unique(tax + 1, tax + 1 + m) - tax - 1;
rep(i, 1, m)
dfs(1, 0);
rep(i, 1, n) cout << ans[i] << '\n';
return 0;
}
雨天的尾巴
考試的時候直接扎第一題上了這到題連暴力都沒打出來t t 心路歷程 其實考試時候還是有可能做出來的,當然關鍵在能否想到線段樹合併。當時想到了離散化 很慌沒打出來。樹上差分,lca倍增,當時覺滴倍增很難打,一看n 100000,於是選擇 用向上標記法,然而少了一行 爆零兩行淚。現在看來倍增真是一點不難啊...
雨天的尾巴題目解析
考試的時候直接扎第一題上了這到題連暴力都沒打出來t t 心路歷程 其實考試時候還是有可能做出來的,當然關鍵在能否想到線段樹合併。當時想到了離散化 很慌沒打出來。樹上差分,lca倍增,當時覺滴倍增很難打,一看n 100000,於是選擇 用向上標記法,然而少了一行 爆零兩行淚。現在看來倍增真是一點不難啊...
bzoj3307 雨天的尾巴
time limit 10 sec memory limit 128 mb submit 258 solved 121 submit status discuss n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每...