标签:
我他妈就是一傻逼。
——题记
第一场多校:出题数0
第一题:
比赛时候的思路挺接近的了。逐个元素考虑,找到能延伸的最大区间,便可以统计该元素对答案的贡献。
所谓能延伸的最大区间就是指这个区间没有所考虑元素的约数。
因为数字的范围很小,所以可以用一个数组来记录每个数字出现的最右的下标。枚举约数,找到所有约数中最右的下标。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 6 using namespace std; 7 8 const int maxn = 100000 + 100; 9 const int MOD = 1000000000 + 7; 10 11 int n; 12 int a[maxn], l[maxn], r[maxn]; 13 int L[maxn], R[maxn]; 14 15 int main() 16 { 17 while(scanf("%d", &n) == 1 && n) 18 { 19 for(int i = 1; i <= n; i++) scanf("%d", a + i); 20 memset(l, 0, sizeof(l)); 21 memset(r, 0, sizeof(r)); 22 23 for(int i = 1; i <= n; i++) 24 { 25 L[i] = 0; 26 for(int j = 1; j <= (int)sqrt(a[i] + 0.5); j++) if(a[i] % j == 0) 27 { 28 L[i] = max(L[i], l[j]); 29 L[i] = max(L[i], l[a[i] / j]); 30 } 31 l[a[i]] = i; 32 } 33 34 for(int i = 1; i <= 10000; i++) r[i] = n + 1; 35 36 for(int i = n; i >= 1; i--) 37 { 38 R[i] = n + 1; 39 for(int j = 1; j <= (int)sqrt(a[i] + 0.5); j++) if(a[i] % j == 0) 40 { 41 R[i] = min(R[i], r[j]); 42 R[i] = min(R[i], r[a[i] / j]); 43 } 44 r[a[i]] = i; 45 } 46 47 int ans = 0; 48 for(int i = 1; i <= n; i++) ans = (ans + (R[i] - i) * (i - L[i])) % MOD; 49 50 printf("%d\n", ans); 51 } 52 53 return 0; 54 }
第二题:
可以用RMQ做,枚举区间左端点,二分右端点,找到合法区间的最右边界。判断是否合法就用RMQ查询区间最大最小值减一下。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 100000 + 10; 7 const int logmaxn = 20; 8 9 int n, k; 10 11 int a[maxn]; 12 13 int _min[maxn][logmaxn], _max[maxn][logmaxn]; 14 15 void RMQ_init() 16 { 17 for(int i = 0; i < n; i++) _min[i][0] = _max[i][0] = a[i]; 18 for(int j = 1; (1 << j) <= n; j++) 19 for(int i = 0; i + (1 << j) - 1 < n; i++) 20 { 21 _min[i][j] = min(_min[i][j-1], _min[i+(1<<(j-1))][j-1]); 22 _max[i][j] = max(_max[i][j-1], _max[i+(1<<(j-1))][j-1]); 23 } 24 } 25 26 void RMQ(int L, int R, int& Min, int& Max) 27 { 28 int k = 0; 29 while((1<<(k+1)) <= R-L+1) k++; 30 Min = min(_min[L][k], _min[R-(1<<k)+1][k]); 31 Max = max(_max[L][k], _max[R-(1<<k)+1][k]); 32 } 33 34 int main() 35 { 36 int T; scanf("%d", &T); 37 while(T--) 38 { 39 scanf("%d%d", &n, &k); 40 for(int i = 0; i < n; i++) scanf("%d", a + i); 41 RMQ_init(); 42 43 long long ans = 0; 44 for(int L = 0; L < n; L++) 45 { 46 int l = L, r = n - 1; 47 while(l < r) 48 { 49 int mid = (l + r) / 2 + 1; 50 int Min, Max; 51 RMQ(L, mid, Min, Max); 52 if(Max - Min < k) l = mid; 53 else r = mid - 1; 54 } 55 ans += r - L + 1; 56 } 57 58 printf("%I64d\n", ans); 59 } 60 61 return 0; 62 }
三四题这种DP表示不会。
第五题,作为一个曾经玩了三年魔方的我表示真的不知道还有这么个结论。
第七题:
上来就敲的这道题,WA了,以为我想得太简单了就弃疗了。
其实是一道很裸的模板题,在原图的基础上把所有最短路的边选出来构一个新图。
最大流求最小割,总边数 - 边最少的最短路,这就是这题的答案。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 #include <map> 7 #define MP make_pair 8 using namespace std; 9 10 typedef pair<int, int> PII; 11 12 const int maxn = 2000 + 100; 13 const int maxm = 60000 + 100; 14 const int INF = 0x3f3f3f3f; 15 int n, m; 16 17 struct Edge 18 { 19 int from, to, dist; 20 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 21 }; 22 23 int d[maxn]; 24 25 struct Dijkstra 26 { 27 int n, m, s, t; 28 bool done[maxn]; 29 vector<Edge> edges; 30 vector<int> G[maxn]; 31 32 void init() { edges.clear(); for(int i = 1; i <= n; i++) G[i].clear(); } 33 34 void AddEdge(int u, int v, int d) 35 { 36 edges.push_back(Edge(u, v, d)); 37 edges.push_back(Edge(v, u, d)); 38 m = edges.size(); 39 G[u].push_back(m - 2); 40 G[v].push_back(m - 1); 41 } 42 43 void dijkstra() 44 { 45 memset(d, 0x3f, sizeof(d)); 46 d[s] = 0; 47 memset(done, false, sizeof(done)); 48 priority_queue<PII, vector<PII>, greater<PII> > Q; 49 Q.push(MP(0, s)); 50 while(!Q.empty()) 51 { 52 PII x = Q.top(); Q.pop(); 53 int u = x.second; 54 if(done[u]) continue; 55 done[u] = true; 56 for(int i = 0; i < G[u].size(); i++) 57 { 58 Edge& e = edges[G[u][i]]; 59 int v = e.to; 60 if(d[v] > d[u] + e.dist) 61 { 62 d[v] = d[u] + e.dist; 63 Q.push(MP(d[v], v)); 64 } 65 } 66 } 67 } 68 }solver; 69 70 struct Edge2 71 { 72 int from, to, cap, flow; 73 Edge2(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {} 74 }; 75 76 struct Dinic 77 { 78 int n, m, s, t; 79 vector<Edge2> edges; 80 vector<int> G[maxn]; 81 bool vis[maxn]; 82 int d[maxn], cur[maxn]; 83 84 void init() { for(int i = 1; i <= n; i++) G[i].clear(); edges.clear(); } 85 86 void AddEdge(int u, int v, int c) 87 { 88 edges.push_back(Edge2(u, v, c, 0)); 89 edges.push_back(Edge2(v, u, 0, 0)); 90 m = edges.size(); 91 G[u].push_back(m - 2); 92 G[v].push_back(m - 1); 93 } 94 95 bool BFS() 96 { 97 memset(vis, false, sizeof(vis)); 98 vis[s] = true; 99 queue<int> Q; 100 Q.push(s); 101 d[s] = 0; 102 103 while(!Q.empty()) 104 { 105 int u = Q.front(); Q.pop(); 106 for(int i = 0; i < G[u].size(); i++) 107 { 108 Edge2& e = edges[G[u][i]]; 109 int v = e.to; 110 if(!vis[v] && e.cap > e.flow) 111 { 112 vis[v] = true; 113 d[v] = d[u] + 1; 114 Q.push(v); 115 } 116 } 117 } 118 119 return vis[t]; 120 } 121 122 int DFS(int u, int a) 123 { 124 if(u == t || a == 0) return a; 125 int flow = 0, f; 126 for(int& i = cur[u]; i < G[u].size(); i++) 127 { 128 Edge2& e = edges[G[u][i]]; 129 int v = e.to; 130 if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap-e.flow))) > 0) 131 { 132 flow += f; 133 e.flow += f; 134 a -= f; 135 edges[G[u][i]^1].flow -= f; 136 if(a == 0) break; 137 } 138 } 139 return flow; 140 } 141 142 int MaxFlow() 143 { 144 int flow = 0; 145 while(BFS()) 146 { 147 memset(cur, 0, sizeof(cur)); 148 flow += DFS(s, INF); 149 } 150 return flow; 151 } 152 }g; 153 154 int a[maxm], b[maxm], c[maxm]; 155 int u[maxm], v[maxm], w[maxm]; 156 157 int main() 158 { 159 while(scanf("%d%d", &n, &m) == 2 && n) 160 { 161 solver.n = n; 162 solver.init(); 163 solver.s = 1, solver.t = n; 164 for(int i = 0; i < m; i++) 165 { 166 int u, v, d; scanf("%d%d%d", a + i, b + i, c + i); 167 solver.AddEdge(a[i], b[i], c[i]); 168 } 169 solver.dijkstra(); 170 171 int cnt = 0; 172 for(int i = 0; i < m; i++) 173 { 174 if(d[a[i]] + c[i] == d[b[i]]) 175 { 176 u[cnt] = a[i]; 177 v[cnt] = b[i]; 178 w[cnt++] = c[i]; 179 } 180 else if(d[b[i]] + c[i] == d[a[i]]) 181 { 182 u[cnt] = b[i]; 183 v[cnt] = a[i]; 184 w[cnt++] = c[i]; 185 } 186 } 187 188 //for(int i = 0; i < cnt; i++) printf("%d %d %d\n", u[i], v[i], w[i]); 189 190 int ans1, ans2; 191 g.n = n; 192 g.s = 1, g.t = n; 193 g.init(); 194 for(int i = 0; i < cnt; i++) g.AddEdge(u[i], v[i], 1); 195 g.BFS(); 196 ans2 = m - g.d[n]; 197 ans1 = g.MaxFlow(); 198 199 printf("%d %d\n", ans1, ans2); 200 } 201 202 return 0; 203 }
第九题:
看懂题目的做法了,但是不懂为什么。
白书上讲了求LCA的倍增算法,属于在线算法。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 using namespace std; 7 8 const int maxn = 100000 + 100; 9 const int logmaxn = 20; 10 11 int n, Q; 12 13 vector<int> G[maxn], w[maxn]; 14 15 set<int> S; 16 17 // LCA 18 int dfs_clock; 19 int dfs[maxn]; 20 int id[maxn]; 21 int dep[maxn]; 22 int fa[maxn]; 23 int cost[maxn]; 24 int anc[maxn][logmaxn]; 25 26 void DFS(int u, int father, int depth) 27 { 28 dfs[u] = ++dfs_clock; 29 id[dfs_clock] = u; 30 fa[u] = father; 31 dep[u] = depth; 32 for(int i = 0; i < G[u].size(); i++) 33 { 34 int v = G[u][i]; 35 if(v == father) continue; 36 cost[v] = cost[u] + w[u][i]; 37 DFS(v, u, depth + 1); 38 } 39 } 40 41 void preprocess() 42 { 43 for(int i = 1; i <= n; i++) 44 { 45 anc[i][0] = fa[i]; 46 for(int j = 1; (1 << j) < n; j++) anc[i][j] = -1; 47 } 48 for(int j = 1; (1 << j) < n; j++) 49 for(int i = 1; i <= n; i++) 50 if(anc[i][j-1] != -1) 51 { 52 int a = anc[i][j-1]; 53 anc[i][j] = anc[a][j-1]; 54 } 55 } 56 57 int LCA(int p, int q) 58 { 59 int log; 60 if(dep[p] < dep[q]) swap(p, q); //dep[p] >= dep[q] 61 for(log = 1; (1 << log) <= dep[p]; log++); log--; 62 63 for(int i = log; i >= 0; i--) 64 if(dep[p] - (1 << i) >= dep[q]) p = anc[p][i]; 65 if(p == q) return p; 66 67 for(int i = log; i >= 0; i--) 68 { 69 if(anc[p][i] != -1 && anc[p][i] != anc[q][i]) 70 { 71 p = anc[p][i]; 72 q = anc[q][i]; 73 } 74 } 75 return fa[p]; 76 } 77 78 int add(int u) 79 { 80 if(S.empty()) return 0; 81 int x, y; 82 set<int>::iterator itx, ity; 83 itx = ity = S.lower_bound(dfs[u]); 84 itx--; 85 if(ity == S.begin() || ity == S.end()) 86 { 87 itx = S.begin(); 88 ity = S.end(); ity--; 89 } 90 x = (*itx); x = id[x]; 91 y = (*ity); y = id[y]; 92 93 return cost[u] - cost[LCA(x, u)] - cost[LCA(y, u)] + cost[LCA(x, y)]; 94 } 95 96 bool inset[maxn]; 97 98 int main() 99 { 100 //freopen("in.txt", "r", stdin); 101 102 int T; scanf("%d", &T); 103 for(int kase = 1; kase <= T; kase++) 104 { 105 printf("Case #%d:\n", kase); 106 107 scanf("%d%d", &n, &Q); 108 for(int i = 1; i <= n; i++) { G[i].clear(); w[i].clear(); } 109 for(int i = 0; i < n - 1; i++) 110 { 111 int u, v, d; scanf("%d%d%d", &u, &v, &d); 112 G[u].push_back(v); w[u].push_back(d); 113 G[v].push_back(u); w[v].push_back(d); 114 } 115 116 dfs_clock = 0; 117 cost[1] = 0; 118 DFS(1, -1, 0); 119 preprocess(); 120 121 int sum = 0; 122 S.clear(); 123 memset(inset, false, sizeof(inset)); 124 while(Q--) 125 { 126 int op, x; scanf("%d%d", &op, &x); 127 if(op == 1 && !inset[x]) 128 { 129 inset[x] = true; 130 sum += add(x); 131 S.insert(dfs[x]); 132 } 133 else if(op ==2 && inset[x]) 134 { 135 inset[x] = false; 136 S.erase(dfs[x]); 137 sum -= add(x); 138 } 139 printf("%d\n", sum); 140 } 141 } 142 143 return 0; 144 }
第二场多校:出题数0
今天心情不好,去刷点别的题发泄一下。改日补
标签:
原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4671455.html