1. 程式人生 > 實用技巧 >jQuery選擇器之層級選擇器(2)

jQuery選擇器之層級選擇器(2)

隨便寫寫吧…

顯然方程式 \(f_{t,u}\) 表示 \(t\) 時間在 \(u\) 的最大貢獻。

\(f_{t,u} = \max\{f_{t-w,v} + c_u\}\)

看到這範圍絕對是矩陣快速冪了…

等等邊權不為\(1\)

那就構造一個長度為 \(5 \times n\) 的向量嘛,然後每過一個時間就會移動。

我們令 \(id(i,j)\)\(position\)\(i\) 的時候,當前時間為 \(6-j\) 的狀態。

然後轉移矩陣是考慮 \(id(i,j+1) \to id(i,j)\) 的,然後連上邊,注意有重邊,如果沒有注意的話會有奇奇怪怪的問題。

如果有一條 \(\{u, v, w\}\)

的邊,我們考慮

base[0][id(u, 6 - w)][id(v, 5)] = c[v];

實際意義是滿足方程式。(

然後就可以轉移了。

預處理 \(\log_2 10^9 = 30\) 個矩陣,向量乘矩陣的複雜度是 \((5n)^2\) 的。

所以複雜度是 \(((5n)^3 + (5n)^2k)\times \log_2 t\)

#include <bits/stdc++.h>

#define FOR(i, x, y) for (int i = x; i <= y; i++)
#define ROF(i, x, y) for (int i = x; i >= y; i--)

int n, m, T, k;
int c[51];
struct buf { int t, x, y; } q[201];

struct Matrix {
	long long a[251][251]; 
	Matrix() { memset(a, 0xc0, sizeof(a)); }
	long long* operator[](int x) { return a[x]; }
} base[31];

struct Vector {
	long long a[251]; 
	Vector() { memset(a, 0xc0, sizeof(a)); }
	long long& operator[](int x) { return a[x]; }
} answer;

int lim;
Matrix mul(Matrix a, Matrix b) {
	Matrix c;
	FOR(i, 1, lim)
		FOR(j, 1, lim)
			FOR(k, 1, lim)
				c[i][j] = std::max(c[i][j], a[i][k] + b[k][j]);
	return c;
}

Vector mul(Vector a, Matrix b) {
	Vector c;
	FOR(i, 1, lim)
		FOR(j, 1, lim)
			c[i] = std::max(c[i], a[j] + b[j][i]);
	return c;
}

int id(int x, int y) { return x + (y - 1) * n; }
int main() {
#ifdef LOCAL
	freopen("testdata.txt", "r", stdin);
#endif
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cin >> n >> m >> T >> k;
	lim = n * 5;
	FOR(i, 1, n) std::cin >> c[i];
	FOR(i, 1, m) {
		int u, v, w;
		std::cin >> u >> v >> w;
		base[0][id(u, 6 - w)][id(v, 5)] = c[v];
	}
	FOR(i, 1, k) {
		int t, x, y;
		std::cin >> t >> x >> y;
		q[i] = {t, x, y};
	}
	std::sort(q + 1, q + k + 1, [](buf x, buf y) { return x.t < y.t; });
	FOR(i, 1, n) FOR(j, 1, 4) base[0][id(i, j + 1)][id(i, j)] = 0;
	FOR(i, 1, 30) base[i] = mul(base[i - 1], base[i - 1]);
	answer[id(1, 5)] = c[1];
	FOR(i, 1, k) {
		int t = q[i].t - q[i - 1].t;
		FOR(j, 0, 30) if (t >> j & 1) answer = mul(answer, base[j]);
		answer[id(q[i].x, 5)] += q[i].y;
	}
	int t = T - q[k].t;
	FOR(j, 0, 30) if (t >> j & 1) answer = mul(answer, base[j]);
	std::cout << std::max(answer[id(1, 5)], -1ll) << '\n';
	return 0;
}