A - Age of Moyu
题意:给出一张图,从1走到n,如果相邻两次走的边的权值不同,花费+1, 否则花费相同,求最小花费
思路:用set记录有当前点的最小花费有多少种方案到达,然后最短路
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int INF = 0x3f3f3f3f; 6 const int maxn = 2e5 + 10; 7 8 struct Edge{ 9 int to, nxt, val; 10 Edge(){} 11 Edge(int to, int nxt, int val):to(to), nxt(nxt), val(val){}; 12 }edge[maxn << 1]; 13 14 set<int>s[maxn]; 15 int head[maxn], tot; 16 17 void Init(int n) 18 { 19 for(int i = 0; i <= n; ++i) head[i] = -1, s[i].clear(); 20 tot = 0; 21 } 22 23 void addedge(int u, int v,int val) 24 { 25 edge[tot] = Edge(v, head[u], val);head[u] = tot++; 26 } 27 28 struct qnode{ 29 int v, c; 30 int pre; 31 int fa; 32 qnode(){} 33 qnode(int v, int c, int pre, int fa) :v(v), c(c), pre(pre), fa(fa){} 34 bool operator < (const qnode &r) const 35 { 36 return c > r.c; 37 } 38 }; 39 40 int n, m; 41 int dist[maxn]; 42 43 void BFS(int st) 44 { 45 for(int i = 1; i <= n; ++i) dist[i] = INF; 46 priority_queue<qnode>q; 47 dist[st] = 0; 48 q.push(qnode(st, 0, 0, 0)); 49 while(!q.empty()) 50 { 51 qnode tmp = q.top(); 52 q.pop(); 53 int u = tmp.v; 54 if(tmp.c > dist[u]) continue; 55 else if(tmp.c == dist[u]) 56 { 57 if(s[u].find(tmp.pre) != s[u].end()) continue; 58 s[u].insert(tmp.pre); 59 } 60 else 61 { 62 dist[u] = tmp.c; 63 s[u].clear(); 64 s[u].insert(tmp.pre); 65 } 66 for(int i = head[u]; ~i; i = edge[i].nxt) 67 { 68 int v = edge[i].to; 69 int cost = edge[i].val; 70 if(v == tmp.fa) continue; 71 if(dist[u] + (cost != tmp.pre) <= dist[v]) 72 { 73 dist[v] = dist[u] + (cost != tmp.pre); 74 if(v != n) 75 { 76 q.push(qnode(v, dist[v], cost, u)); 77 } 78 } 79 } 80 } 81 } 82 83 int main() 84 { 85 int t; 86 while(scanf("%d %d", &n, &m) != EOF) 87 { 88 Init(n); 89 for(int i = 1; i <= m; ++i) 90 { 91 int u, v, w; 92 scanf("%d %d %d", &u, &v ,&w); 93 addedge(u, v, w); 94 addedge(v, u, w); 95 } 96 BFS(1); 97 if(dist[n] == INF) dist[n] = -1; 98 printf("%d\n", dist[n]); 99 } 100 return 0; 101 }
B - AraBellaC
留坑。
C - YJJ’s Stack
留坑。
D - Go to school
留坑。
E - GuGuFishtion
留坑。
F - Lord Li's problem
留坑。
G - Reverse Game
留坑。
H - Traffic Network in Numazu
题意:两种操作,第一种是更改一条边权的值,第二种是查询x-y的最短路径,给出的是一颗树加一条边
思路:将形成环的边单独拿出来考虑,那么考虑是否经过这条边使得答案更优,修改操作用线段树或者树状数组维护
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const int maxn = 1e5 + 10; 8 const int DEG = 20; 9 10 struct EDGE{ 11 int u, v, w; 12 }EDGE[maxn], TEMP; 13 14 struct Edge{ 15 int to, nxt, val; 16 Edge(){} 17 Edge(int to, int nxt, int val) :to(to), nxt(nxt), val(val){} 18 }edge[maxn << 1]; 19 20 int head[maxn], tot, cnt; 21 int father[maxn]; 22 23 void Init(int n) 24 { 25 for(int i = 0; i <= n; ++i) head[i] = -1, father[i] = i; 26 tot = cnt = 0; 27 } 28 29 int find(int x) 30 { 31 return x == father[x] ? father[x] : father[x] = find(father[x]); 32 } 33 34 void mix(int x,int y) 35 { 36 x = find(x), y = find(y); 37 if(x != y) father[x] = y; 38 } 39 40 bool same(int x,int y) 41 { 42 return find(x) == find(y); 43 } 44 45 void addedge(int u, int v, int val) 46 { 47 edge[tot] = Edge(v, head[u], val); head[u] = tot++; 48 } 49 50 int dro[maxn]; 51 int ord[maxn], son[maxn]; 52 int fa[maxn][DEG]; 53 int deg[maxn]; 54 55 void DFS(int u, int pre) 56 { 57 ord[u] = ++cnt; 58 dro[cnt] = u; 59 for(int i = 1; i < DEG; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1]; 60 for(int i = head[u]; ~i; i = edge[i].nxt) 61 { 62 int v = edge[i].to; 63 if(v == pre) continue; 64 fa[v][0] = u; 65 deg[v] = deg[u] + 1; 66 DFS(v, u); 67 } 68 son[u] = cnt; 69 } 70 71 int LCA(int u, int v) 72 { 73 if(deg[u] > deg[v]) swap(u, v); 74 int hu = deg[u], hv = deg[v]; 75 int tu = u, tv = v; 76 for(int det = hv - hu, i = 0; det; det >>= 1, ++i) 77 { 78 if(det & 1) 79 { 80 tv = fa[tv][i]; 81 } 82 } 83 if(tu == tv) return tu; 84 for(int i = DEG - 1; i >= 0; --i) 85 { 86 if(fa[tu][i] == fa[tv][i]) continue; 87 tu = fa[tu][i]; 88 tv = fa[tv][i]; 89 } 90 return fa[tu][0]; 91 } 92 93 struct node{ 94 int l, r; 95 ll val, lazy; 96 node(){} 97 node(int l,int r, ll val, ll lazy) :l(l), r(r), val(val), lazy(lazy){} 98 }tree[maxn << 2]; 99 100 void pushup(int id) 101 { 102 tree[id].val = tree[id << 1].val + tree[id << 1 | 1].val; 103 } 104 105 void pushdown(int id) 106 { 107 if(tree[id].lazy) 108 { 109 ll lazy = tree[id].lazy; 110 tree[id << 1].val += lazy; 111 tree[id << 1 | 1].val += lazy; 112 tree[id << 1].lazy += lazy; 113 tree[id << 1 | 1].lazy += lazy; 114 tree[id].lazy = 0; 115 } 116 } 117 118 void build(int id, int l, int r) 119 { 120 tree[id] = node(l, r, 0, 0); 121 if(l == r) return ; 122 int mid = (l + r) >> 1; 123 build(id << 1, l, mid); 124 build(id << 1 | 1, mid + 1, r); 125 } 126 127 void update(int id, int l, int r, ll val) 128 { 129 if(l <= tree[id].l && r >= tree[id].r) 130 { 131 tree[id].val += val; 132 tree[id].lazy += val; 133 return ; 134 } 135 pushdown(id); 136 int mid = (tree[id].l + tree[id].r) >> 1; 137 if(mid >= l) update(id << 1, l, r, val); 138 if(r > mid) update(id << 1 | 1, l, r, val); 139 pushup(id); 140 } 141 142 ll query(int id, int pos) 143 { 144 if(tree[id].l == pos && tree[id].r == pos) 145 { 146 return tree[id].val; 147 } 148 pushdown(id); 149 int mid = (tree[id].l + tree[id].r) >> 1; 150 if(pos <= mid) return query(id << 1, pos); 151 if(pos > mid) return query(id << 1 | 1, pos); 152 pushup(id); 153 } 154 155 ll getdis(int u,int v) 156 { 157 int root = LCA(u, v); 158 return query(1, ord[u]) + query(1, ord[v]) - 2 * query(1, ord[root]); 159 } 160 161 int n, q; 162 163 int main() 164 { 165 int t; 166 scanf("%d", &t); 167 while(t--) 168 { 169 scanf("%d %d", &n, &q); 170 Init(n); 171 for(int i = 1; i <= n; ++i) 172 { 173 scanf("%d %d %d", &EDGE[i].u, &EDGE[i].v, &EDGE[i].w); 174 int u = EDGE[i].u, v = EDGE[i].v, w = EDGE[i].w; 175 if(same(u, v)) 176 { 177 TEMP = EDGE[i]; 178 continue; 179 } 180 mix(u, v); 181 addedge(u, v, w); 182 addedge(v, u, w); 183 } 184 fa[1][0] = 1; 185 deg[1] = 0; 186 DFS(1, -1); 187 build(1, 1, n); 188 for(int i = 1; i <= n; ++i) 189 { 190 int u = EDGE[i].u, v = EDGE[i].v, w = EDGE[i].w; 191 if(u == TEMP.u && v == TEMP.v) continue; 192 if(fa[u][0] == v) 193 { 194 update(1, ord[u], son[u], w); 195 } 196 else if(fa[v][0] == u); 197 { 198 update(1, ord[v], son[v], w); 199 } 200 } 201 // for(int i = 1; i <= n; ++i) cout << ord[i] << endl; 202 // for(int i = 1; i <= n; ++i) cout << i << " " << query(1, ord[i]) << endl; 203 while(q--) 204 { 205 int op, x, y; 206 scanf("%d %d %d", &op, &x ,&y); 207 if(op == 0) 208 { 209 int u = EDGE[x].u, v = EDGE[x].v, w = EDGE[x].w; 210 if(u == TEMP.u && v == TEMP.v) 211 { 212 EDGE[x].w = y; 213 TEMP.w = y; 214 } 215 if(fa[u][0] == v) 216 { 217 update(1, ord[u], son[u], y - w); 218 } 219 else if(fa[v][0] == u) 220 { 221 update(1, ord[v], son[v], y - w); 222 } 223 EDGE[x].w = y; 224 } 225 else if(op == 1) 226 { 227 ll ans = getdis(x, y); 228 ans = min(ans, getdis(x, TEMP.u) + TEMP.w + getdis(y, TEMP.v)); 229 ans = min(ans, getdis(y, TEMP.u) + TEMP.w + getdis(x, TEMP.v)); 230 231 printf("%lld\n", ans); 232 } 233 } 234 } 235 return 0; 236 }
I - Tree
题意:一棵树种,每个点有一个权值,表示可以向上跳几步,两种操作,一种是修改某点权值,还有一种是询问某个点需要跳几次跳出
思路:DFS序分块,弹飞绵阳升级版,注意更新的时候,维护一个$In[u]$ 表示最远跳到块内是第几块,这样就不用多一个log
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 namespace FastIO 5 { 6 #define BUF_SIZE 10000005 7 bool IOerror = false; 8 inline char NC() 9 { 10 static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; 11 if (p1 == pend) 12 { 13 p1 = buf; 14 pend = buf + fread(buf, 1, BUF_SIZE, stdin); 15 if (pend == p1) 16 { 17 IOerror = true; 18 return -1; 19 } 20 } 21 return *p1++; 22 } 23 24 inline bool blank(char ch) 25 { 26 return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; 27 } 28 29 template <typename T> 30 inline void read(T &x) 31 { 32 char ch; 33 while (blank(ch = NC())); 34 if (IOerror) 35 { 36 x = -1; 37 return; 38 } 39 bool flag = false; 40 if (ch == '-') 41 { 42 flag = true; 43 ch = NC(); 44 } 45 if (!isdigit(ch)) while (!isdigit(ch = NC())); 46 for (x = ch - '0'; isdigit(ch = NC()); x = x * 10 + ch - '0'); 47 if (flag) x *= -1; 48 } 49 50 void out(int x) 51 { 52 if (x / 10) out(x / 10); 53 putchar(x % 10 + '0'); 54 } 55 56 inline void print(int x) 57 { 58 out(x); 59 puts(""); 60 } 61 #undef BUF_SIZE 62 }using namespace FastIO; 63 64 #define N 100010 65 #define DEG 20 66 #define block 400 67 68 int t, n, q; 69 int a[N], b[N], In[N], Out[N], fa[N][20], deep[N], p[N], fp[N], cnt; 70 vector <int> G[N]; 71 72 void Init() 73 { 74 for (int i = 1; i <= n; ++i) G[i].clear(); 75 cnt = 0; fa[1][0] = 1; deep[1] = 0; 76 } 77 78 void DFS(int u) 79 { 80 p[u] = ++cnt; 81 fp[cnt] = u; 82 for (int i = 1; i < DEG; ++i) 83 fa[u][i] = fa[fa[u][i - 1]][i - 1]; 84 for (auto v : G[u]) if (v != fa[u][0]) 85 { 86 deep[v] = deep[u] + 1; 87 DFS(v); 88 } 89 } 90 91 int GetK(int x, int k) 92 { 93 bitset <20> b; b = k; 94 for (int i = 19; i >= 0; --i) if (b[i]) 95 x = fa[x][i]; 96 return x; 97 } 98 99 int query(int x) 100 { 101 int res = 0; 102 x = p[x]; 103 while (x) 104 { 105 res += b[x]; 106 x = Out[x]; 107 } 108 return res; 109 } 110 111 void update(int x) 112 { 113 if (a[x] > deep[x]) 114 { 115 b[p[x]] = 1; 116 Out[p[x]] = 0; 117 In[p[x]] = p[x]; 118 } 119 else 120 { 121 int root = GetK(x, a[x]); 122 if ((p[root] - 1) / block != (p[x] - 1) / block) 123 { 124 b[p[x]] = 1; 125 Out[p[x]] = p[root]; 126 In[p[x]] = p[x]; 127 } 128 else 129 { 130 b[p[x]] = b[p[root]] + 1; 131 Out[p[x]] = Out[p[root]]; 132 In[p[x]] = p[root]; 133 } 134 } 135 x = p[x]; 136 for (int i = x + 1; i <= n && (i - 1) / block == (x - 1) / block; ++i) 137 { 138 if (In[i] != i) 139 { 140 b[i] = b[In[i]] + 1; 141 Out[i] = Out[In[i]]; 142 } 143 } 144 } 145 146 void Run() 147 { 148 read(t); 149 while (t--) 150 { 151 read(n); Init(); 152 for (int i = 2; i <= n; ++i) 153 { 154 read(fa[i][0]); 155 G[fa[i][0]].push_back(i); 156 } DFS(1); 157 for (int i = 1; i <= n; ++i) read(a[i]); 158 for (int i = 1; i <= n; ++i) 159 { 160 int x = fp[i]; 161 if (a[x] > deep[x]) 162 { 163 b[i] = 1; 164 Out[i] = 0; 165 In[i] = i; 166 continue; 167 } 168 int root = GetK(x, a[x]); 169 if ((p[root] - 1) / block != (i - 1) / block) 170 { 171 b[i] = 1; 172 Out[i] = p[root]; 173 In[i] = i; 174 } 175 else 176 { 177 b[i] = b[p[root]] + 1; 178 Out[i] = Out[p[root]]; 179 In[i] = p[root]; 180 } 181 } 182 read(q); 183 for (int i = 1, op, x, v; i <= q; ++i) 184 { 185 read(op); read(x); 186 if (op == 1) print(query(x)); 187 else 188 { 189 read(v); 190 a[x] = v; 191 update(x); 192 } 193 } 194 } 195 } 196 197 int main() 198 { 199 #ifdef LOCAL 200 freopen("Test.in", "r", stdin); 201 #endif 202 203 Run(); 204 return 0; 205 }
J - Sequence
题意:求$F_n = C * F_{n - 2} + D * F_{n - 1} + \lfloor{\frac {p}{n}}\rfloor$
思路:考虑 最后一项最多有$\sqrt n 项 按这个值分块矩阵快速幂即可$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 6 const ll MOD = (ll)1e9 + 7; 7 8 int t, n; 9 ll A, B, C, D, P; 10 11 ll Biner(ll x) 12 { 13 ll l = x, r = n, res = l; 14 x = P / x; 15 while (r - l >= 0) 16 { 17 ll mid = (l + r) >> 1; 18 ll tmp = P / mid; 19 if (tmp >= x) 20 { 21 l = mid + 1; 22 res = mid; 23 } 24 else 25 r = mid - 1; 26 } 27 return res; 28 } 29 30 struct node 31 { 32 ll a[3][3]; 33 node () 34 { 35 memset(a, 0, sizeof a); 36 } 37 node operator * (const node &r) const 38 { 39 node ans = node(); 40 for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) 41 ans.a[i][j] = (ans.a[i][j] + a[i][k] * r.a[k][j] % MOD) % MOD; 42 return ans; 43 } 44 }base; 45 46 node qmod(node base, int n) 47 { 48 node res = node(); 49 res.a[0][0] = B, res.a[0][1] = A; res.a[0][2] = 1; 50 while (n) 51 { 52 if (n & 1) res = res * base; 53 base = base * base; 54 n >>= 1; 55 } 56 return res; 57 } 58 59 ll work() 60 { 61 if (n == 1) return A; 62 if (n == 2) return B; 63 int l = 3, r; 64 while (l <= n) 65 { 66 r = Biner(l); 67 base.a[2][0] = P / l; 68 node res = qmod(base, r - l + 1); 69 B = res.a[0][0], A = res.a[0][1]; 70 l = r + 1; 71 } 72 return B; 73 } 74 75 int main() 76 { 77 scanf("%d", &t); 78 while (t--) 79 { 80 scanf("%lld%lld%lld%lld%lld%d", &A, &B, &C, &D, &P, &n); 81 memset(base.a, 0, sizeof base.a); 82 base.a[0][0] = D, base.a[1][0] = C, base.a[0][1] = 1; base.a[2][2] = 1; 83 printf("%lld\n", work()); 84 } 85 return 0; 86 }
K - Swordsman
题意:有五种攻击属性,怪物有五种防御属性,所有攻击属性要大于其对应的防御属性便能将其击杀,击杀后有经验加成,求最多杀死多少怪物
思路:用5个set 依次维护即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 namespace FastIO 5 { 6 #define BUF_SIZE 10000005 7 bool IOerror = false; 8 inline char NC() 9 { 10 static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; 11 if (p1 == pend) 12 { 13 p1 = buf; 14 pend = buf + fread(buf, 1, BUF_SIZE, stdin); 15 if (pend == p1) 16 { 17 IOerror = true; 18 return -1; 19 } 20 } 21 return *p1++; 22 } 23 24 inline bool blank(char ch) 25 { 26 return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; 27 } 28 29 template <typename T> 30 inline void read(T &x) 31 { 32 char ch; 33 while (blank(ch = NC())); 34 if (IOerror) 35 { 36 x = -1; 37 return; 38 } 39 bool flag = false; 40 if (ch == '-') 41 { 42 flag = true; 43 ch = NC(); 44 } 45 if (!isdigit(ch)) while (!isdigit(ch = NC())); 46 for (x = ch - '0'; isdigit(ch = NC()); x = x * 10 + ch - '0'); 47 if (flag) x *= -1; 48 } 49 #undef BUF_SIZE 50 }using namespace FastIO; 51 52 const int maxn = 1e5 + 10; 53 54 struct node{ 55 int id; 56 int v; 57 node(){} 58 node(int id, int v) :id(id), v(v){} 59 bool operator < (const node &r) const{ 60 return v > r.v; 61 } 62 }; 63 64 priority_queue<node>q[10]; 65 66 int n, k; 67 int ans[maxn]; 68 int arr[maxn][20]; 69 70 int main() 71 { 72 int t; 73 read(t); 74 while(t--) 75 { 76 read(n), read(k); 77 for(int i = 1; i <= k; ++i) while(!q[i].empty()) q[i].pop(); 78 for(int i = 1; i <= k; ++i) read(ans[i]); 79 for(int i = 1; i <= n; ++i) 80 { 81 for(int j = 1; j <= (k * 2); ++j) 82 { 83 read(arr[i][j]); 84 } 85 q[1].push(node(i, arr[i][1])); 86 } 87 int cnt = 0; 88 while(1) 89 { 90 bool flag = false; 91 for(int i = 1; i <= k; ++i) 92 { 93 while(!q[i].empty()) 94 { 95 node tmp = q[i].top(); 96 if(tmp.v <= ans[i]) 97 { 98 if(i == k) 99 { 100 cnt++; 101 flag = true; 102 for(int j = 1; j <= k; ++j) ans[j] += arr[tmp.id][j + k]; 103 } 104 else 105 { 106 tmp.v = arr[tmp.id][i + 1]; 107 q[i + 1].push(tmp); 108 } 109 q[i].pop(); 110 } 111 else break; 112 } 113 } 114 if(!flag) break; 115 } 116 printf("%d\n", cnt); 117 for(int i = 1; i <= k; ++i) printf("%d%c", ans[i], " \n"[i == k]); 118 } 119 return 0; 120 }