首先,這不是正解,甚至歪的很過分,你還要吸氧,但是我就是要發。
根據題意我們可以知道首先要求
- 轉移的路徑編號的轉移必須是從小到大
- 轉移的權值必須從小到大
- 一條邊的終點轉移到另一條邊的起點,起點終點需要相同
我的思路是什麼呢,這是三個要求,而且頭兩個要求很二維偏序對不對,那麼第三個要求我們可以稍稍強行理解一下一下然後上CDQ分治,畢竟模板的CDQ分治就是三維偏序。
要考慮怎麼寫CDQ分治,首先這裏的瓶頸是什麼就是條件三,那我們在CDQ分治的時候就可以和普通的處理不太一樣,我們之前的處理都是處理中點之前的修改,回答中點之後的詢問,利用樹狀數組去解決。但是如果在這題我們直接使用樹狀數組的話會有一個問題,你當前邊的權值爲V,你在樹狀數組裏找權值小於V的最大值有可能那條邊是非法的,就是不能滿足條件3.
我們的處理方案是什麼呢,就是遍歷一遍區間,把所有的點拿出來,按照修改的終點和查詢的起點相同的那些路拿出來單獨處理,分多次處理,這樣樹狀數組裏的都是合法的值都可以轉移。然後由於總邊數是固定的,所以這樣子的操作不會改變複雜度。
由於樹狀數組的log,所以總複雜度是兩個log,但是又由於我們在路上用了很多stl,所以常數有點大,你還得丟人的去吸氧。
int B[max_], MC = 1e5 + 7;
inline void Ins(int i, int x) { for (; i <= MC; i += i & -i) B[i] = max(B[i], x); }
inline void Clr(int i) { for (; i <= MC; i += i & -i) B[i] = 0; }
inline int Qur(int i) { int A = 0; for (; i; i -= i & -i) A = max(A, B[i]); return A; }
int N, M,qn;
struct kk {
int op, id, now, to, val,yuanid;//op = 1;修改 ,op = 0是詢問
kk(){}
kk(int a, int b, int c, int d, int e,int f) {
op = a, id = b, now = c, to = d, val = e,yuanid = f;
}
}node[2 * max_];
queue<kk> que[max_];
set<int> S;
int f[max_];
void dfs(int L, int R) {
if (L == R)return;
int mid = (L + R) >> 1;
dfs(L, mid);
for (int i = L; i <= R; i++) {
if (node[i].id <= mid && node[i].op == 1) {//修改
if (!S.count(node[i].to))S.insert(node[i].to);
que[node[i].to].push(node[i]);
}
if (node[i].id > mid && node[i].op == 0) {//詢問
if (!S.count(node[i].now))S.insert(node[i].now);
que[node[i].now].push(node[i]);
}
}
for (auto quanzhi : S) {
set<int> del;
while (!que[quanzhi].empty()){
kk tou = que[quanzhi].front(); que[quanzhi].pop();
if (tou.op == 1) {
if (!del.count(tou.val))del.insert(tou.val);
Ins(tou.val, f[tou.yuanid]);
}
else {
int t = Qur(tou.val - 1);
f[tou.yuanid] = max(f[tou.yuanid], t + 1);
}
}
for (auto to : del) {
Clr(to);
}
del.clear();
}
S.clear();
dfs(mid + 1, R);
}
signed main() {
N = read(); M = read();
for (int i = 1; i <= M; i++) {
f[i] = 1;
int now = read(), to = read(), val = read();
++qn;node[qn] = kk(0, qn, now, to, val + 1,i);
++qn; node[qn] = kk(1, qn, now, to, val + 1,i);
}
dfs(1, qn);
int ans = 0;
for (int i = 1; i <= M; i++) {
//cout << f[i] << " ";
ans = max(ans, f[i]);
}
cout << ans;
return 0;
}