\(T1\) \(1h30min\)c++
\(T2\) \(1h30min\)數組
\(T3\) \(0min\)優化
\(T1\) \(100pts\)spa
\(T2\) \(96pts\).net
\(T3\) \(0pts\)code
輸出文件名打錯,錯誤比較嚴重,就算程序打得再好,文件名錯了,照樣零分,和沒打一個樣。感謝老師改了過來。時間分配較爲合理,腦子今天比較活,多上廁所或許可使腦子思路更清晰。
題目名稱叫作線段樹,可是這個題不必定是用線段樹去作。排序
若是用線段樹去作,每一次操做都是單點的,因此還不如不用。it
看題目提供的操做有兩個單點操做,一個區間操做(所有修改),這樣的複雜度最壞的狀況是O(nq),很不理想。io
咱們須要優化,能夠優化的有這麼幾點: 1. 咱們能夠維護一個sum值,在改變的時候能夠O(1)的輸出。 2. 咱們能夠設一個變量flag爲全局值,就是操做三的要修改成的數。再設一個flag_x爲flag是第幾回修改,記錄下標。Tag數組能夠記錄第j個數在第幾回變成了flag。再在該基礎上修改序列值。
通過優化,每一次操做都是O(1)的,因此咱們的總複雜度能夠下降到O(q)的複雜度,因此是能夠過的。class
最長路,聽上去與最短路相似,因此可能會用dij或者SPFA法,一開始我打了一個堆優化dij,可是該複雜度是能拿到40pts,並不太行。
而後看到保證必定有最長路,那麼這又是一個有向圖,因此就是有向無環圖,DAG。可使用拓撲排序+dp來求最長路。
每一次都是用入度爲零的點開始推這個點所能夠到達的點的最長路。狀態轉移方程大約是
dp[v] = max(dp[v], dp[u]+t[i].dis)
u
是指該邊起點;v
是指該邊的終點,t[i].dis
是指該邊的長度.
而後就在轉移中取一個max就作完了。
#include <bits/stdc++.h> typedef long long ll; const int Max = 1e7 + 80; const int MAXSIZE = 50000020; int bufpos; char buf[MAXSIZE]; int re() { int val = 0; for(; buf[bufpos] < '0' || buf[bufpos] > '9'; bufpos ++); for(; buf[bufpos] >= '0' && buf[bufpos] <= '9'; bufpos ++) val = val * 10 + buf[bufpos] - '0'; return val; } void write(ll x) { if(x < 0) x = - x, putchar('-'); if(x > 9) write(x / 10); putchar(x % 10 ^ 48); } int n, q, a[Max], flag, tag[Max], flag_x = 0; ll sum = 0; int main() { freopen("segmenttree.in", "r", stdin); freopen("segmenttree.out", "w", stdout); buf[fread(buf, 1, MAXSIZE, stdin)] = '\0'; bufpos = 0; n = re(); q = re(); for(int i = 1; i <= q; i ++) { int opt = re(); if(opt == 1) { int x = re(), y = re(); if(tag[x] == flag_x) sum -= a[x]; else { tag[x] = flag_x; sum -= flag; } sum += y; a[x] = y; } else if(opt == 2) { int x = re(), y = re(); if(tag[x] == flag_x) { a[x] += y; } else { a[x] = flag + y; tag[x] = flag_x; } sum += y; } else { int y = re(); flag = y; flag_x = i; sum = y * n; } write(sum); putchar('\n'); } return 0; }
#include <cstdio> #include <queue> #define re register typedef long long ll; const int Max = 1e6 + 150; const ll INF = 0x7ffffff; const int MAXSIZE = 50000020; int bufpos; char buf[MAXSIZE]; inline ll max(ll a, ll b) { return a > b ? a : b;} inline int read() { int val = 0; for(; buf[bufpos] < '0' || buf[bufpos] > '9'; bufpos ++); for(; buf[bufpos] >= '0' && buf[bufpos] <= '9'; bufpos ++) val = val * 10 + buf[bufpos] - '0'; return val; } struct edge { ll to, net, dis; }t[Max]; int n, m, head[Max], cnt, du[Max]; ll dp[Max], ans = -INF; inline void insert(ll u, ll v, ll w) { t[++cnt].to = v; t[cnt].net = head[u]; t[cnt].dis = w; head[u] = cnt; } std :: queue<int> q; int main() { freopen("lpsa.in", "r", stdin); freopen("lpsa.out", "w", stdout); buf[fread(buf, 1, MAXSIZE, stdin)] = '\0'; bufpos = 0; n = read(); m = read(); for(int i = 1; i <= m; i ++){ int u = read(), v = read(), w = read(); insert(u, v, w); du[v] ++; } for(re int i = 1; i <= n; ++ i) if(du[i] == 0) q.push(i); int u, v; while(!q.empty()) { u = q.front(); q.pop(); for(re int i = head[u]; i; i = t[i].net) { v = t[i].to; dp[v] = max(dp[v], dp[u] + t[i].dis); ans = max(ans, dp[v]); du[v] --; if(du[v] == 0) q.push(v); } } printf("%lld\n", ans); return 0; }