CF960F CDQ分治

首先,這不是正解,甚至歪的很過分,你還要吸氧,但是我就是要發。
根據題意我們可以知道首先要求

  1. 轉移的路徑編號的轉移必須是從小到大
  2. 轉移的權值必須從小到大
  3. 一條邊的終點轉移到另一條邊的起點,起點終點需要相同

我的思路是什麼呢,這是三個要求,而且頭兩個要求很二維偏序對不對,那麼第三個要求我們可以稍稍強行理解一下一下然後上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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章