离线强化训练
Posted Algorithms Crush Me
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了离线强化训练相关的知识,希望对你有一定的参考价值。
10.17
看似在线,实际每个数字独立,可以每种数字拆出来考虑,转变为树上单点修改询问链。
维护差分,变为子树修改,单点询问,排好dfs序后用线段树维护。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 #include <set> 6 using namespace std; 7 const int maxn = 1e5 + 10; 8 int a[maxn], c[maxn]; 9 vector<int> b, g[maxn]; 10 int op[200005], I[200005], J[200005], X[200005], ans[200005]; 11 12 typedef pair<int, int> pii; 13 vector<pii> q[300005]; 14 set<int> S; 15 set<int> :: iterator it; 16 17 // LCA 18 int dfs_clock = 0; 19 int dep[maxn], l[maxn], r[maxn]; 20 int anc[maxn][33]; 21 void dfs(int x, int fa) 22 { 23 l[x] = r[x] = ++dfs_clock; 24 for(int i = 0; i < g[x].size(); i++) 25 { 26 int to = g[x][i]; 27 if(to == fa) continue; 28 dep[to] = dep[x] + 1; 29 anc[to][0] = x; 30 dfs(to, x); 31 r[x] = r[to]; 32 } 33 } 34 void LCA_init(int n) 35 { 36 for(int j = 1; (1 << j) < n; j++) 37 for(int i = 1; i <= n; i++) if(anc[i][j-1]) 38 anc[i][j] = anc[anc[i][j-1]][j-1]; 39 } 40 int LCA(int u, int v) 41 { 42 int log; 43 if(dep[u] < dep[v]) swap(u, v); 44 for(log = 0; (1 << log) < dep[u]; log++); 45 for(int i = log; i >= 0; i--) 46 if(dep[u] - (1<<i) >= dep[v]) u = anc[u][i]; 47 if(u == v) return u; 48 for(int i = log; i >= 0; i--) 49 if(anc[u][i] && anc[u][i] != anc[v][i]) 50 u = anc[u][i], v = anc[v][i]; 51 return anc[u][0]; 52 } 53 54 // segment_tree 55 int tag[maxn<<2]; 56 void modify(int p, int tl, int tr, int l, int r, int x) 57 { 58 if(tr < l || r < tl) return; 59 if(l <= tl && tr <= r) 60 { 61 tag[p] += x; 62 return; 63 } 64 int mid = (tl + tr) >> 1; 65 modify(p<<1, tl, mid, l, r, x); 66 modify(p<<1|1, mid+1, tr, l, r, x); 67 } 68 int query(int p, int tl, int tr, int x) 69 { 70 if(x == 0) return 0; 71 int ret = tag[p]; 72 if(tl == tr) return ret; 73 int mid = (tl + tr) >> 1; 74 if(x <= mid) ret += query(p<<1, tl, mid, x); 75 else ret += query(p<<1|1, mid+1, tr, x); 76 return ret; 77 } 78 79 int main(void) 80 { 81 int N, Q; 82 scanf("%d %d", &N, &Q); 83 for(int i = 1; i <= N; i++) scanf("%d", a + i), b.push_back(a[i]); 84 for(int i = 1; i < N; i++) 85 { 86 int u, v; 87 scanf("%d %d", &u, &v); 88 g[u].push_back(v); 89 g[v].push_back(u); 90 } 91 for(int i = 1; i <= Q; i++) 92 { 93 char s[11]; 94 scanf("%s", s); 95 if(s[0] == ‘C‘) 96 { 97 op[i] = 1; 98 scanf("%d %d", I + i, X + i); 99 } 100 else 101 { 102 op[i] = 2; 103 scanf("%d %d %d", I + i, J + i, X + i); 104 } 105 b.push_back(X[i]); 106 } 107 sort(b.begin(), b.end()); 108 b.erase(unique(b.begin(), b.end()), b.end()); 109 for(int i = 1; i <= N; i++) a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1; 110 for(int i = 1; i <= Q; i++) X[i] = lower_bound(b.begin(), b.end(), X[i]) - b.begin() + 1; 111 for(int i = 1; i <= N; i++) c[i] = a[i], q[c[i]].push_back(pii(1, i)); 112 for(int i = 1; i <= Q; i++) 113 { 114 if(op[i] == 1) 115 { 116 q[c[I[i]]].push_back(pii(-1, I[i])); 117 q[X[i]].push_back(pii(1, I[i])); 118 c[I[i]] = X[i]; 119 } 120 else q[X[i]].push_back(pii(0, i)); 121 } 122 dfs(1, 0); 123 LCA_init(N); 124 for(int i = 1; i <= b.size(); i++) 125 { 126 for(int j = 0; j < q[i].size(); j++) 127 { 128 int x = q[i][j].first, y = q[i][j].second; 129 if(x == 1) modify(1, 1, N, l[y], r[y], 1), S.insert(y); 130 if(x == -1) modify(1, 1, N, l[y], r[y], -1), S.erase(y); 131 if(x == 0) ans[y] = query(1, 1, N, l[I[y]]) + query(1, 1, N, l[J[y]]) - query(1, 1, N, l[LCA(I[y], J[y])]) - query(1, 1, N, l[anc[LCA(I[y], J[y])][0]]); 132 } 133 for(it = S.begin(); it != S.end(); it++) modify(1, 1, N, l[*it], r[*it], -1); 134 S.clear(); 135 } 136 for(int i = 1; i <= Q; i++) 137 if(op[i] == 2) printf("%d\n", ans[i]); 138 return 0; 139 }
以上是关于离线强化训练的主要内容,如果未能解决你的问题,请参考以下文章