正睿20NOIp前冲刺day11
估分:100+100+10+10=220
实际:100+20+10+10=140
T1:
原题
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 inline int read() 8 { 9 int x = 0, f = 0; 10 char ch = getchar(); 11 while (!isdigit(ch)) f = ch == '-', ch = getchar(); 12 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 13 return f ? -x : x; 14 } 15 16 const int N = 1000010; 17 const int INF = 0x3f3f3f3f; 18 19 int n; 20 int dep[N], f[N], rev[N]; 21 int h[N], num[N << 1], nex[N << 1], dqx; 22 23 void add(int a, int b) 24 { 25 num[dqx] = b; 26 nex[dqx] = h[a]; 27 h[a] = dqx++; 28 } 29 30 void dfs(int u, int pa) 31 { 32 int cnt = 0, res = 0; 33 for (int i = h[u]; ~i; i = nex[i]) 34 { 35 int j = num[i]; 36 if (j == pa) continue; 37 dep[j] = dep[u] + 1; 38 dfs(j, u); 39 f[u] = f[u] + f[j]; 40 if (rev[j] + 1 <= dep[u]) 41 { 42 f[u] += rev[j] + 1 - dep[u]; 43 rev[u] = max(rev[u], rev[j] + 1); 44 cnt++; 45 } 46 res++; 47 } 48 if (cnt != res) rev[u] = INF; 49 else f[u] += dep[u] - rev[u]; 50 if (nex[h[u]] == -1 && u != 1) rev[u] = 0, f[u] = dep[u]; 51 } 52 53 int main() 54 { 55 n = read(); 56 memset(h, -1, sizeof(h)); 57 for (int i = 2; i <= n; i++) 58 { 59 int a = read(), b = read(); 60 add(a, b), add(b, a); 61 } 62 dfs(1, 0); 63 printf("%d", f[1]); 64 }
T2:
把点的坐标从二维转为一维的时候没判纵坐标刚好是r的情况,丢了80pts
二分答案就行,判断答案可行的时候优先队列优化一下就好
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 #define mp make_pair 9 #define int long long 10 11 typedef pair<int, int> PII; 12 13 inline int read() 14 { 15 int x = 0, f = 0; 16 char ch = getchar(); 17 while (!isdigit(ch)) f = ch == '-', ch = getchar(); 18 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 19 return f ? -x : x; 20 } 21 22 const int N = 100010; 23 24 int n, m, K; 25 int tu[N], tc[N]; 26 int dx[6] = { 0,0,-1,-1,1,1 }, dy[6] = { -1,1,0,1,-1,0 }; 27 28 inline int get(int id, int k) 29 { 30 int x = id / m + 1, y = id % m; 31 y == 0 ? y = m : 0; 32 33 int a = x + dx[k], b = y + dy[k]; 34 if (!a || !b || a > n || b > m) return 0; 35 return (a - 1) * m + b; 36 } 37 38 inline int ned(int u, int k, int d, priority_queue<PII>& que) 39 { 40 int v = get(u, k); 41 if (!v) return 0; 42 43 int x = 0; 44 if (tc[v] < d) 45 { 46 x = d - tc[v]; 47 tc[v] = d; 48 que.push(mp(tc[v], v)); 49 } 50 return x; 51 } 52 53 inline int check(int x) 54 { 55 priority_queue<PII> que; 56 memcpy(tc, tu, sizeof(tu)); 57 for (int i = 1; i <= n * m; i++) que.push(mp(tc[i], i)); 58 59 int res = 0; 60 while (!que.empty()) 61 { 62 int u = que.top().second, vd = que.top().first; 63 que.pop(); 64 65 if (vd ^ tc[u]) continue; 66 67 int d = tc[u] - x; 68 res += ned(u, 0, d, que); 69 res += ned(u, 1, d, que); 70 res += ned(u, 2, d, que); 71 res += ned(u, 3, d, que); 72 res += ned(u, 4, d, que); 73 res += ned(u, 5, d, que); 74 75 } 76 return res; 77 } 78 79 signed main() 80 { 81 n = read(), m = read(), K = read(); 82 83 for (int i = 1, k = 1; i <= n; i++) 84 { 85 for (int j = 1; j <= m; j++, k++) 86 { 87 int x = read(); 88 tu[k] = x; 89 } 90 } 91 92 int l = 0, r = 1e12; 93 while (l < r) 94 { 95 register int mid = (l + r) >> 1; 96 if (check(mid) <= K) r = mid; 97 else l = mid + 1; 98 } 99 100 printf("%lld", l); 101 }
T3:
就会10pts暴力
先类似于数位DP的预处理出C(i,j),表示当二进制下是1的最高位是i,一共有j个1的方案数。之后对于每个询问,枚举1的数量i。可以发现一个区间按1的数量分组,分为w组,然后把这些组排序后发现区间[a,b]中最多只有边界的两组被拆分,所以把在[a,b]内的区间都加起来,剩下两个单独处理就行了
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 9 int C[50][50]; 10 11 inline int read() 12 { 13 int x = 0, f = 0; 14 char ch = getchar(); 15 while (!isdigit(ch)) f = ch == '-', ch = getchar(); 16 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 17 return f ? -x : x; 18 } 19 20 int count(int n, int i) 21 { 22 int c = 0, ans = 0; 23 for (int j = 29; ~j; j--) 24 { 25 if (n >> j & 1) 26 { 27 if (i >= c) ans += C[j][i - c]; 28 ++c; 29 } 30 } 31 return ans + (c == i); 32 } 33 34 LL sum(int n, int i) 35 { 36 int c = 0, v = 0; 37 LL ans = 0; 38 for (int j = 29; ~j; j--) 39 { 40 if (n >> j & 1) 41 { 42 if (i >= c) ans += (LL)v * C[j][i - c]; 43 if (i > c && j > 0) ans += ((1ll << j) - 1) * C[j - 1][i - c - 1]; 44 ++c, v += 1 << j; 45 } 46 } 47 return ans + (c == i ? n : 0); 48 } 49 50 int get_rank(int n, int i, int k) 51 { 52 int c = count(n, i), l = 1, r = n; 53 while (l <= r) 54 { 55 int m = l + r >> 1; 56 if (c - count(m - 1, i) >= k) l = m + 1; 57 else r = m - 1; 58 } 59 return l - 1; 60 } 61 62 int main() 63 { 64 for (int i = 0; i <= 30; i++) 65 { 66 C[i][0] = 1; 67 for (int j = 1; j <= i; j++) C[i][j] = C[i - 1][j] + C[i - 1][j - 1]; 68 } 69 70 int T = read(); 71 while (T--) 72 { 73 int L = read(), R = read(), a = read(), b = read(); 74 75 int cnt = 0; 76 LL ans = 0; 77 for (int i = 30; i; i--) 78 { 79 int c = count(R, i) - count(L - 1, i); 80 if (cnt < a && b <= cnt + c) 81 { 82 int r = get_rank(R, i, a - cnt), l = get_rank(R, i, b - cnt); 83 ans += sum(r, i) - sum(l - 1, i); 84 } 85 else if (cnt < a && a <= cnt + c) 86 { 87 int r = get_rank(R, i, a - cnt); 88 ans += sum(r, i) - sum(L - 1, i); 89 } 90 else if (a <= cnt && cnt + c < b) ans += sum(R, i) - sum(L - 1, i); 91 else if (a <= cnt && cnt < b) 92 { 93 int l = get_rank(R, i, b - cnt); 94 ans += sum(R, i) - sum(l - 1, i); 95 } 96 97 cnt += c; 98 if (cnt > b) break; 99 } 100 printf("%lld\n", ans); 101 } 102 }
T4:
10pts暴力
总结:
第二题又粗心写炸了,写代码一定得认真点才行
浙公网安备 33010602011771号