正睿20NOIp前冲刺day12
估分:60+20+30=110
实际:40+20+10=70
T1:
写了个分治,是错的,正解不会证,没写
如果只考虑朝上走,就是求出每个点可以走到的点,倍增。之后看往下走的一段。对于一条链,如果体力都是满的从两边开始走,那么复活的次数是一样的。因为这个等价于将整条序列分成尽量少的段,使得每一段之和都不小于k ,所以从两边开始贪心都是对的。所以可以找到拐下去的点之后,从下往上倍增。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 #define int long long 8 9 const int N = 200010, M = 4010; 10 11 int n, k, cnt; 12 int len[N], dep[N], f[N][30], F[N][30], tot, ans; 13 int h[N], num[N << 1], nex[N << 1], v[N << 1], dqx; 14 15 void add(int a, int b, int c) 16 { 17 num[dqx] = b; 18 v[dqx] = c; 19 nex[dqx] = h[a]; 20 h[a] = dqx++; 21 } 22 23 void dfs1(int x, int pa) 24 { 25 dep[x] = dep[pa] + 1; 26 for (int i = 0; i <= 19; i++) f[x][i + 1] = f[f[x][i]][i]; 27 for (int i = h[x]; ~i; i = nex[i]) 28 { 29 int y = num[i]; 30 if (y == pa) continue; 31 f[y][0] = x; 32 len[y] = len[x] + v[i]; 33 dfs1(y, x); 34 } 35 } 36 37 void dfs2(int x, int pa) 38 { 39 int tot = 0, t = x; 40 for (int i = 20; ~i; i--) 41 { 42 if (len[x] - len[f[x][i]] < k - tot) 43 { 44 tot += len[x] - len[f[x][i]]; 45 x = f[x][i]; 46 } 47 } 48 49 F[t][0] = f[x][0], x = t; 50 for (int i = 0; i <= 19; i++) F[x][i + 1] = F[F[x][i]][i]; 51 for (int i = h[x]; ~i; i = nex[i]) 52 { 53 int j = num[i]; 54 if (j == pa) continue; 55 dfs2(j, x); 56 } 57 } 58 59 int LCA(int x, int y) 60 { 61 if (dep[x] < dep[y]) swap(x, y); 62 for (int i = 20; ~i; i--) 63 { 64 if (dep[f[x][i]] >= dep[y]) x = f[x][i]; 65 } 66 if (x == y) return x; 67 for (int i = 20; ~i; i--) 68 { 69 if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; 70 } 71 return f[x][0]; 72 } 73 74 signed main() 75 { 76 scanf("%lld%lld", &n, &k); 77 78 memset(h, -1, sizeof(h)); 79 for (int i = 1; i < n; i++) 80 { 81 int x, y, z; 82 scanf("%lld%lld%lld", &x, &y, &z); 83 add(x, y, z), add(y, x, z); 84 } 85 86 dfs1(1, 0); 87 dfs2(1, 0); 88 89 int q; 90 scanf("%d", &q); 91 while (q--) 92 { 93 int x, y; 94 scanf("%lld%lld", &x, &y); 95 int c = LCA(x, y); 96 ans = tot = 0; 97 for (int i = 20; i >= 0; i--) 98 { 99 if (dep[F[x][i]] >= dep[c]) 100 { 101 x = F[x][i], ans += (1 << i); 102 } 103 } 104 105 tot += len[x] - len[c]; 106 if (k - tot <= len[y] - len[c]) 107 { 108 ans++, x = y; 109 for (int i = 20; i >= 0; i--) if (len[f[y][i]] - len[c] >= k - tot) y = f[y][i]; 110 c = y; 111 for (int i = 20; i >= 0; i--) 112 { 113 if (dep[F[x][i]] >= dep[c]) 114 { 115 x = F[x][i]; 116 ans += (1 << i); 117 } 118 } 119 120 } 121 printf("%lld\n", ans); 122 } 123 }
T2:
20pts暴力
T3:
写了个20pts的图论,错的
总结:
这次代码到是没炸,但算法都没对,下次有啥思路直接写吧,这次的第一题就因为不会证没写所以没A掉