zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营 第四场

    应该是目前为止最简单的一场。没来得及做的题待补。

    题目链接:https://ac.nowcoder.com/acm/contest/884#question


    A:

    注意虚树直径即可。

    B:

    最近多校特别多线性基的题目。这题是线段树维护线性基的交。

      1 /* basic header */
      2 #include <bits/stdc++.h>
      3 /* define */
      4 #define ll long long
      5 #define dou double
      6 #define pb emplace_back
      7 #define mp make_pair
      8 #define sot(a,b) sort(a+1,a+1+b)
      9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
     10 #define rep0(i,a,b) for(int i=a;i<b;++i)
     11 #define eps 1e-8
     12 #define int_inf 0x3f3f3f3f
     13 #define ll_inf 0x7f7f7f7f7f7f7f7f
     14 #define lson (curpos<<1)
     15 #define rson (curpos<<1|1)
     16 /* namespace */
     17 using namespace std;
     18 /* header end */
     19 
     20 const int maxn = 1e5 + 10;
     21 struct LinerBase {
     22     int cnt;
     23     ll b[32];
     24     void init() {
     25         cnt = 0;
     26         memset(b, 0, sizeof(b));
     27     }
     28     int insert(ll x) {
     29         for (int i = 31; i >= 0; i--)
     30             if (x & (1ll << i)) {
     31                 if (b[i]) x ^= b[i];
     32                 else {
     33                     b[i] = x;
     34                     cnt++;
     35                     return 1;
     36                 }
     37             }
     38         return 0;
     39     }
     40     bool check(ll x) {
     41         for (int i = 31; i >= 0; i--)
     42             if (x & (1ll << i)) x ^= b[i];
     43         return x == 0;
     44     }
     45 };
     46 
     47 LinerBase merge(LinerBase &a, LinerBase &b) {
     48     LinerBase c, d, all;
     49     for (int i = 31; i >= 0; i--) {
     50         c.b[i] = 0;
     51         all.b[i] = a.b[i];
     52         d.b[i] = 1ll << i;
     53     }
     54     for (int i = 31; i >= 0; i--)
     55         if (b.b[i]) {
     56             ll v = b.b[i], k = 0; int jud = 1;
     57             for (int j = 31; j >= 0; j--)
     58                 if ((1ll << j) & v)
     59                     if (all.b[j]) {
     60                         v ^= all.b[j];
     61                         k ^= d.b[j];
     62                     } else {
     63                         jud = 0;
     64                         all.b[j] = v;
     65                         d.b[j] = k;
     66                         break;
     67                     }
     68             if (jud) {
     69                 ll cur = 0;
     70                 for (int j = 31; j >= 0; j--)
     71                     if (k & (1ll << j)) cur ^= a.b[j];
     72                 c.insert(cur);
     73             }
     74         }
     75     return c;
     76 }
     77 LinerBase segt[maxn << 2], a[maxn];
     78 
     79 void maintain(int curpos) {
     80     segt[curpos] = merge(segt[lson], segt[rson]);
     81 }
     82 
     83 void build(int curpos, int curl, int curr) {
     84     if (curl == curr) {
     85         segt[curpos] = a[curl];
     86         return;
     87     }
     88     int mid = curl + curr >> 1;
     89     build(lson, curl, mid); build(rson, mid + 1, curr);
     90     maintain(curpos);
     91 }
     92 
     93 bool query(int curpos, ll x, int curl, int curr, int ql, int qr) {
     94     if (ql <= curl && curr <= qr)
     95         return segt[curpos].check(x);
     96     int mid = curl + curr >> 1;
     97     if (qr <= mid) return query(lson, x, curl, mid, ql, qr);
     98     if (ql > mid) return query(rson, x, mid + 1, curr, ql, qr);
     99     return query(lson, x, curl, mid, ql, qr) && query(rson, x, mid + 1, curr, ql, qr);
    100 }
    101 
    102 int n, m;
    103 
    104 int main() {
    105     scanf("%d%d", &n, &m);
    106     rep1(i, 1, n) {
    107         int _size; scanf("%d", &_size);
    108         rep1(j, 1, _size) {
    109             ll x; scanf("%lld", &x);
    110             a[i].insert(x);
    111         }
    112     }
    113     build(1, 1, n);
    114     while (m--) {
    115         int l, r; ll x; scanf("%d%d%lld", &l, &r, &x);
    116         if (query(1, x, 1, n, l, r)) puts("YES");
    117         else puts("NO");
    118     }
    119     return 0;
    120 }
    View Code

    C:

    这题是2018年南昌网络赛原题(几乎,用同样做法可过),题目链接:https://nanti.jisuanke.com/t/38228

    枚举区间的复杂度已经是O(n^2),完全无法接受。但不同区间的最小值情况最多只有n种。而且对于一个最小值a[i],一定存在l,r使得a[i]*sum(bl..r)最大。

    那么对于任意一个a[i],假设其为最小值,往左往右扩展确定最大的区间位置;然后分两种情况:

    1. 若a[i]>=0,那么显然要使得sum[r]-sum[l-1]最大。因为不知道具体会确定哪个区间,那么可以把最终的区间[l,r]分为[l,i]和[i,r]两个一端确定的区间,就变成查询max(b[i]-b[l])+max(b[r]-b[i])。由于线段树只能返回值而不能返回在b数组中的位置,所以可以建立两个数组分别记录b数组的前缀后缀和,然后在这两个数组上建线段树即可。
    2. 若a[i]<0,把上面的max改成min,同样做法。
     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 3e6 + 10;
    21 ll a[maxn], b[maxn], s1[maxn], s2[maxn], ans = -1e18;
    22 int n, l[maxn], r[maxn];
    23 
    24 struct SegT {
    25     struct Node {
    26         ll maxx, minn;
    27     } node[maxn << 2];
    28 
    29     void build(ll *s, int curpos, int curl, int curr) {
    30         if (curl == curr) {
    31             node[curpos].maxx = node[curpos].minn = s[curl];
    32             return;
    33         }
    34         int mid = curl + curr >> 1;
    35         build(s, lson, curl, mid); build(s, rson, mid + 1, curr);
    36         node[curpos].maxx = max(node[lson].maxx, node[rson].maxx);
    37         node[curpos].minn = min(node[lson].minn, node[rson].minn);
    38     }
    39 
    40     ll queryMax(int curpos, int curl, int curr, int ql, int qr) {
    41         if (ql <= curl && curr <= qr) return node[curpos].maxx;
    42         int mid = curl + curr >> 1;
    43         if (qr <= mid) return queryMax(lson, curl, mid, ql, qr);
    44         if (ql > mid) return queryMax(rson, mid + 1, curr, ql, qr);
    45         return max(queryMax(lson, curl, mid, ql, mid), queryMax(rson, mid + 1, curr, mid + 1, qr));
    46     }
    47 
    48     ll queryMin(int curpos, int curl, int curr, int ql, int qr) {
    49         if (ql <= curl && curr <= qr) return node[curpos].minn;
    50         int mid = curl + curr >> 1;
    51         if (qr <= mid) return queryMin(lson, curl, mid, ql, qr);
    52         if (ql > mid) return queryMin(rson, mid + 1, curr, ql, qr);
    53         return min(queryMin(lson, curl, mid, ql, mid), queryMin(rson, mid + 1, curr, mid + 1, qr));
    54     }
    55 } segt1, segt2;
    56 
    57 void determinLR() {
    58     stack<int>st; st.push(1);
    59     l[1] = 1; r[n] = n;
    60     rep1(i, 2, n) {
    61         while (!st.empty() && a[i] <= a[st.top()]) st.pop();
    62         if (st.empty()) l[i] = 1; else l[i] = st.top() + 1;
    63         st.push(i);
    64     }
    65     while (!st.empty()) st.pop();
    66     st.push(n);
    67     for (int i = n - 1; i >= 1; i--) {
    68         while (!st.empty() && a[i] <= a[st.top()]) st.pop();
    69         if (st.empty()) r[i] = n; else r[i] = st.top() - 1;
    70         st.push(i);
    71     }
    72 }
    73 
    74 int main() {
    75     scanf("%d", &n);
    76     s1[0] = s2[n + 1] = 0;
    77     rep1(i, 1, n) scanf("%lld", &a[i]);
    78     rep1(i, 1, n) {
    79         scanf("%lld", &b[i]);
    80         s1[i] = s1[i - 1] + b[i];
    81     }
    82     for (int i = n; i >= 1; i--) s2[i] = s2[i + 1] + b[i];
    83     segt1.build(s1, 1, 1, n); segt2.build(s2, 1, 1, n);
    84     determinLR();
    85     rep1(i, 1, n) {
    86         ll lsum = segt2.queryMax(1, 1, n, l[i], i) - s2[i + 1], rsum = segt1.queryMax(1, 1, n, i, r[i]) - s1[i - 1];
    87         ll tmp = a[i] * (lsum + rsum - b[i]);
    88         ans = max(tmp, ans);
    89         lsum = segt2.queryMin(1, 1, n, l[i], i) - s2[i + 1], rsum = segt1.queryMin(1, 1, n, i, r[i]) - s1[i - 1];
    90         tmp = a[i] * (lsum + rsum - b[i]);
    91         ans = max(ans, tmp);
    92     }
    93     printf("%lld
    ", ans);
    94     return 0;
    95 }
    View Code

    D:

    当时打了个表看了几分钟,突然有种感觉:对于有解的不能被3整除的数n,一定只用两个数就能或出来吗?

    答案是显然的。分类讨论n%3的结果即可。

      1 /* basic header */
      2 #include <bits/stdc++.h>
      3 /* define */
      4 #define ll long long
      5 #define dou double
      6 #define pb emplace_back
      7 #define mp make_pair
      8 #define sot(a,b) sort(a+1,a+1+b)
      9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
     10 #define rep0(i,a,b) for(int i=a;i<b;++i)
     11 #define eps 1e-8
     12 #define int_inf 0x3f3f3f3f
     13 #define ll_inf 0x7f7f7f7f7f7f7f7f
     14 #define lson (curpos<<1)
     15 #define rson (curpos<<1|1)
     16 /* namespace */
     17 using namespace std;
     18 /* header end */
     19 
     20 const int maxn = 1e2 + 10;
     21 int func[maxn];
     22 
     23 int main() {
     24     int t; scanf("%d", &t);
     25     while (t--) {
     26         ll n; scanf("%lld", &n);
     27         if (n % 3 == 0) {
     28             printf("1 %lld
    ", n);
     29             continue;
     30         }
     31         ll cmp = n;
     32         int cnt = 0;
     33         while (cmp) {
     34             func[++cnt] = cmp & 1;
     35             cmp >>= 1;
     36         }
     37         rep0(i, 2, cnt) {
     38             ll ans1 = 0, ans2 = 0;
     39             for (int j = cnt; j >= i + 1; j--) ans1 = ans1 * 2 + func[j];
     40             for (int j = i; j >= 1; j--) ans2 = ans2 * 2 + func[j];
     41             rep1(j, 1, i) ans1 *= 2;
     42             if (ans2 % 3 == 1) {
     43                 rep1(j, i + 1, cnt)
     44                 if (j % 2 == 0 && func[j]) {
     45                     ans2 |= (1ll << j - 1);
     46                     break;
     47                 }
     48                 int flag = 0;
     49                 if (ans2 % 3 != 0)
     50                     rep1(j, i + 1, cnt)
     51                     if (j % 2 == 1 && func[j]) {
     52                         if (!flag)flag = j;
     53                         else {
     54                             ans2 |= (1ll << flag - 1); ans2 |= (1ll << j - 1);
     55                             break;
     56                         }
     57                     }
     58             } else if (ans2 % 3 == 2) {
     59                 rep1(j, i + 1, cnt)
     60                 if (j % 2 == 1 && func[j]) {
     61                     ans2 |= (1ll << j - 1);
     62                     break;
     63                 }
     64                 int flag = 0;
     65                 if (ans2 % 3 != 0)
     66                     rep1(j, i + 1, cnt)
     67                     if (j % 2 == 0 && func[j]) {
     68                         if (!flag)flag = j;
     69                         else {
     70                             ans2 |= (1ll << flag - 1); ans2 |= (1ll << j - 1);
     71                             break;
     72                         }
     73                     }
     74             }
     75             if (ans2 % 3 != 0)continue;
     76             if (ans1 % 3 == 1) {
     77                 rep1(j, 1, i)
     78                 if (j % 2 == 0 && func[j]) {
     79                     ans1 |= (1ll << j - 1);
     80                     break;
     81                 }
     82                 int flag = 0;
     83                 if (ans2 % 3 != 0)
     84                     rep1(j, 1, i)
     85                     if (j % 2 == 1 && func[j]) {
     86                         if (!flag) flag = j;
     87                         else {
     88                             ans1 |= (1ll << flag - 1); ans1 |= (1ll << j - 1);
     89                             break;
     90                         }
     91                     }
     92             } else if (ans1 % 3 == 2) {
     93                 rep1(j, 1, i)
     94                 if (j % 2 == 1 && func[j]) {
     95                     ans1 |= (1ll << j - 1);
     96                     break;
     97                 }
     98                 int flag = 0;
     99                 if (ans1 % 3 != 0)
    100                     rep1(j, 1, i)
    101                     if (j % 2 == 0 && func[j]) {
    102                         if (!flag) flag = j;
    103                         else {
    104                             ans1 |= (1ll << flag - 1); ans1 |= (1ll << j - 1);
    105                             break;
    106                         }
    107                     }
    108             }
    109             if (ans1 % 3 != 0)continue; if ((ans1 | ans2) != n)continue;
    110             printf("2 %lld %lld
    ", ans1, ans2);
    111             break;
    112         }
    113     }
    114 }
    View Code

    E:

    dp。

    F:

    线段树+平衡树。

    G:

    树型dp。

    H:

    高斯消元数学题。

    I:

    字符串题。广义后缀自动机。

    J:

    dp+最短路。dp[i][j]表示从起点走到编号为i的点,至多免费走j条边的花费的最小值。

    dp[i][j]=min(dp[i][j-1],min(dp[x][j-1],dp[x][j]+e)) 其中点x和点i有边权为e的边。

    从小到大枚举j进行转移,以min(dp[i][j-1],dp[x][j-1])作为点i距离的初始值。时间复杂度O(kmlogn)。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 1e3 + 10;
    21 struct Edge {
    22     int u, v, w;
    23 } edge[maxn << 1];
    24 int head[maxn], nxt[maxn << 1], tot = 0, dp[maxn][maxn];
    25 
    26 void init() {
    27     tot = 0;
    28     rep0(i, 0, maxn) head[i] = 0;
    29     rep0(i, 0, maxn * 2) nxt[i] = 0;
    30     rep0(i, 0, maxn) rep0(j, 0, maxn) dp[i][j] = int_inf;
    31 }
    32 
    33 void addEdge(int u, int v, int w) {
    34     nxt[++tot] = head[u];
    35     head[u] = tot;
    36     edge[tot].u = u;
    37     edge[tot].v = v;
    38     edge[tot].w = w;
    39 }
    40 
    41 struct Node {
    42     int x, d, k;
    43     Node() {}
    44     Node(int a, int b, int c): x(a), d(b), k(c) {}
    45     bool operator<(const Node &rhs)const {
    46         return d > rhs.d;
    47     }
    48 };
    49 
    50 int dijkstra(int s, int t, int k) {
    51     priority_queue<Node, vector<Node>>q;
    52     dp[s][k] = 0;
    53     q.push(Node(s, 0, k));
    54     while (!q.empty()) {
    55         Node curr = q.top();
    56         q.pop();
    57         int u = curr.x, d = curr.d, k = curr.k;
    58         if (d > dp[u][k]) continue;
    59         if (u == t) return d;
    60         for (int i = head[u]; i; i = nxt[i]) {
    61             int v = edge[i].v, w = edge[i].w;
    62             if (k && dp[v][k - 1] > d) {
    63                 dp[v][k - 1] = d;
    64                 q.push(Node(v, d, k - 1));
    65             }
    66             if (dp[v][k] > d + w) {
    67                 dp[v][k] = d + w;
    68                 q.push(Node(v, d + w, k));
    69             }
    70         }
    71     }
    72 }
    73 
    74 int main() {
    75     init();
    76     int n, m, s, t, k; scanf("%d%d%d%d%d", &n, &m, &s, &t, &k);
    77     rep0(i, 0, m) {
    78         int u, v, w; scanf("%d%d%d", &u, &v, &w);
    79         if (u == v) continue;
    80         addEdge(u, v, w); addEdge(v, u, w);
    81     }
    82     printf("%d
    ", dijkstra(s, t, k));
    83     return 0;
    84 }
    View Code

    K:

    给定一个数字序列,问:该数字序列有多少个子序列,其值能被300整除。

    注意到300的整数既能被3整除又能被100整除。对于被3整除,用一个数组记录前缀和%3的结果即可;对于被100整除,判断最后两位是否都为0。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 // const int maxn = 1e5 + 10;
    21 const int maxn = 10;
    22 char s[maxn];
    23 int n, pre[maxn], cnt[3];
    24 
    25 int main() {
    26     scanf("%s", s + 1); n = strlen(s + 1);
    27     rep1(i, 1, n) pre[i] = (pre[i - 1] + s[i] - '0') % 3;
    28     ll ans = 0;
    29     rep1(i, 1, n) {
    30         if (s[i] == '0') {
    31             ans++; // 算单独0
    32             if (s[i - 1] == '0') ans += cnt[pre[i - 1]]; // 如果前一位也是0,满足被100整除的要求
    33         }
    34         cnt[pre[i - 1]]++;
    35     }
    36     printf("%lld
    ", ans);
    37     return 0;
    38 }
    View Code
  • 相关阅读:
    [Music]Cool Whispers
    [转]PE文件格式详解(下)
    [English]商务交际英语口语集锦
    [转]GC并不是.Net的宠儿 A garbage collector for C and C++
    [Music]A Place Nearby
    [转]Linux操作系统下 MONO执行C#程序的方法
    ANSI C and objectoriented programming
    [转]关于sizeof()的一些思考
    [转]PE文件格式详解(上)
    [Music]Candle in the Wind 1997《风中之烛》缅怀戴安娜
  • 原文地址:https://www.cnblogs.com/JHSeng/p/11257269.html
Copyright © 2011-2022 走看看