正睿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 }
View Code

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 }
View Code

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 }
View Code

T4:

  10pts暴力

总结:

  第二题又粗心写炸了,写代码一定得认真点才行

posted on 2020-10-26 20:36  ArrogHie  阅读(141)  评论(0)    收藏  举报