zoukankan      html  css  js  c++  java
  • 2018年全国多校算法寒假训练营练习比赛(第五场)题解

    题目链接

    A - 逆序数

    经典问题,有很多方法,例如树状数组,线段树,归并排序、分治等。代码不贴了。

    B - Big Water Problem

    单点修改求区间和,树状数组或者线段树都可以。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    long long c[maxn];
     
    int lowbit(int x) {
      return x & (-x);
    }
     
    long long sum(int p) {
      long long res = 0;
      while(p) {
        res += c[p];
        p -= lowbit(p);
      }
      return res;
    }
     
    void update(int x, long long y) {
      while(x < maxn) {
        c[x] += y;
        x += lowbit(x);
      }
    }
     
    int main() {
       
      int n, m;
      scanf("%d%d", &n, &m);
      for(int i = 1; i <= n; i ++) {
        long long x;
        scanf("%lld", &x);
        update(i, x);
      }
      while(m --) {
        int op;
        scanf("%d", &op);
        if(op == 1) {
          int x;
          long long y;
          scanf("%d%lld", &x, &y);
          update(x, y);
        } else {
          int L, R;
          scanf("%d%d", &L, &R);
          printf("%lld
    ", sum(R) - sum(L - 1));
        }
      }
      return 0;
    }
    

    C - 字符串的问题

    比赛中暴力从大到小枚举前缀长度,KMP验证一下就 AC 了?还要思考一下复杂度究竟对不对。

    #include <iostream>
    #include <cstring>
    using namespace std;
     
    const int N = 1000010;
    int nx[N];
    char S[N], T[N];
    int slen, tlen;
     
    void getNext()
    {
      int j, k;
      j = 0; k = -1; nx[0] = -1;
      while(j < tlen)
        if(k == -1 || T[j] == T[k])
          nx[++j] = ++k;
        else
          k = nx[k];
       
    }
     
    /*
     返回模式串在主串S中出现的次数
     */
    int KMP_Count()
    {
      int ans = 0;
      int i, j = 0;
       
      if(slen == 1 && tlen == 1)
      {
        if(S[0] == T[0])
          return 1;
        else
          return 0;
      }
      getNext();
      for(i = 0; i < slen; i++)
      {
        while(j > 0 && S[i] != T[j])
          j = nx[j];
        if(S[i] == T[j])
          j++;
        if(j == tlen)
        {
          ans++;
          j = nx[j];
        }
      }
      return ans;
    }
     
    /*
    int main()
    {
       
      int TT;
      int i, cc;
      cin>>TT;
      while(TT--)
      {
        cin>>S>>T;
        slen = strlen(S);
        tlen = strlen(T);
        cout<<"模式串T在主串S中首次出现的位置是: "<<KMP_Index()<<endl;
        cout<<"模式串T在主串S中出现的次数为: "<<KMP_Count()<<endl;
      }
      return 0;
    }
     */
     
    int check(int x) {
      int p1 = 0;
      int p2 = slen - x;
      while(p1 <= x - 1) {
        if(S[p1] != S[p2]) return 0;
        p1 ++;
        p2 ++;
      }
       
      for(int i = 0; i < x; i ++) {
        T[i] = S[i];
        T[i + 1] = 0;
      }
       
      tlen = x;
      if(KMP_Count() >= 3) return 1;
      return 0;
    }
     
    int main() {
      scanf("%s", S);
      slen = strlen(S);
      int ans = 0;
      int L = 1, R = slen;
      for(int i = slen - 1; i >= 1; i --) {
        if(check(i)) {
          ans = i;
          break;
        }
      }
      if(ans == 0) printf("Just a legend
    ");
      else {
        for(int i = 0; i < ans; i ++) {
          printf("%c", S[i]);
        }
        printf("
    ");
      }
    }
    

    D - 集合问题

    写了一堆暴力模拟规则就搞过去了,看到有并查集AC的,有待学习。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 110000;
    int n;
    int A, B;
    int a[maxn];
    map<int, int> belong;
    map<int, bool> flag;
     
    int main() {
      int fail = 0;
      scanf("%d%d%d", &n, &A, &B);
      for(int i = 1; i <= n; i ++) {
        scanf("%d", &a[i]);
        flag[a[i]] = 1;
      }
      sort(a + 1, a + 1 + n);
      if(A == B) {
        for(int i = 1; i <= n; i ++) {
          if(flag[B - a[i]] == 0) {
            fail = 1;
            break;
          }
          belong[a[i]] = 2;
        }
      } else {
        while(1) {
          if(fail) break;
          int ss = 0;
          for(int i = 1; i <= n; i ++) {
            if(belong[a[i]]) continue;
            if(flag[A - a[i]] == 0 && flag[B - a[i]] == 0) {
              fail = 1;
              break;
            } else if(flag[A - a[i]] == 1 && (flag[B - a[i]] == 0 || belong[B - a[i]])) {
              if(belong[A - a[i]] == 2) {
                fail = 1;
                break;
              }
              belong[a[i]] = 1;
              belong[A - a[i]] = 1;
              ss = 1;
            } else if((flag[A - a[i]] == 0 || belong[A - a[i]]) && flag[B - a[i]] == 1) {
              if(belong[B - a[i]] == 1) {
                fail = 1;
                break;
              }
              belong[a[i]] = 2;
              belong[B - a[i]] = 2;
              ss = 1;
            } else {
              if(A - a[i] != a[i] && B - a[i] != a[i]) {
                if(belong[A - a[i]] == 0 && belong[B - a[i]] == 0) {
                  continue;
                } else if(belong[A - a[i]]) {
                  belong[a[i]] = belong[A - a[i]];
                  ss = 1;
                } else {
                  belong[a[i]] = belong[B - a[i]];
                  ss = 1;
                }
              } else if(A - a[i] == a[i]) {
                if(belong[B - a[i]] == 1) {
                  fail = 1;
                  break;
                }
                belong[a[i]] = 2;
                belong[B - a[i]] = 2;
                ss = 1;
              } else {
                if(belong[A - a[i]] == 2) {
                  fail = 1;
                  break;
                }
                belong[a[i]] = 1;
                belong[A - a[i]] = 1;
                ss = 1;
              }
            }
          }
          if(fail) break;
          if(ss == 0) break;
        }
      }
       
      if(fail == 0) {
        for(int i = 1; i <= n; i ++) {
          if(belong[a[i]] == 1 && belong[A - a[i]] != 1) fail = 1;
          if(belong[a[i]] == 2 && belong[B - a[i]] != 2) fail = 1;
        }
      }
       
      if(fail) {
        printf("NO
    ");
      } else {
        printf("YES
    ");
        for(int i = 1; i <= n; i ++) {
          printf("%d", belong[a[i]] - 1);
          if(i < n) printf(" ");
          else printf("
    ");
        }
      }
       
      return 0;
    }
    

    E - 情人节的电灯泡

    单点更新,求子矩阵和,二维树状数组即可。

    #include <bits/stdc++.h>
    using namespace std;
     
     
    const int maxn = 1010;
    int n, m;
     
    int C[maxn][maxn];
    int a[maxn][maxn];
     
    int lowbit(int x) {
      return x & (-x);
    }
     
    void add(int x, int y, int c){
      for(int i = x; i <= n; i += lowbit(i)){
        for(int j = y; j <= n; j += lowbit(j)){
          C[i][j] += c;
        }
      }
    }
     
    int sum(int x,int y){
      int ret = 0;
      for(int i = x; i > 0; i -= lowbit(i)){
        for(int j = y;j > 0;j -= lowbit(j)){
          ret += C[i][j];
        }
      }
      return ret;
    }
     
    int main() {
      scanf("%d%d", &n, &m);
      for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j ++) {
          scanf("%d", &a[i][j]);
          add(i, j, a[i][j]);
        }
      }
      while(m --) {
        int op;
        scanf("%d", &op);
        if(op == 1) {
          int x, y;
          scanf("%d%d", &x, &y);
          if(a[x][y] == 1) {
            add(x, y, -1);
          } else {
            add(x, y, 1);
          }
          a[x][y] = (a[x][y] ^ 1);
        } else {
          int x1, y1, x2, y2;
          scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
          printf("%d
    ", sum(x2, y2) - sum(x1 - 1, y2) - sum(x2, y1 - 1) + sum(x1-1, y1-1));
        }
      }
      return 0;
    }
    

    F - The Biggest Water Problem

    模拟一下就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    
    long long n;
    
    long long work(long long x) {
      long long res = 0;
      while(x) {
        res += x % 10;
        x = x / 10;
      }
      return res;
    }
    
    int main() {
      scanf("%d", &n);
      while(1) {
        if(n <= 9) {
          printf("%lld
    ", n);
          break;
        }
        n = work(n);
      }
      return 0;
    }
    

    G - 送分啦-QAQ

    该题和HDU 2516一样

    H - Tree Recovery

    区间加,区间求和,线段树就可以了。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
     
    int n, Q;
    long long sum[4 * maxn];
    long long f[4 * maxn];
     
    void pushDown(int l, int r, int rt) {
      if(f[rt] == 0) return;
      int mid = (l + r) / 2;
      int len_left = (mid - l + 1);
      int len_right = (r - mid);
      f[2 * rt] += f[rt];
      f[2 * rt + 1] += f[rt];
      sum[2 * rt] += f[rt] * len_left;
      sum[2 * rt + 1] += f[rt] * len_right;
      f[rt] = 0;
    }
     
    void pushUp(int rt) {
      sum[rt] =sum[2 * rt] + sum[2 * rt + 1];
    }
     
    void build(int l, int r, int rt) {
      if(l == r) {
        scanf("%lld", &sum[rt]);
        return;
      }
      int mid = (l + r) / 2;
      build(l, mid, 2 * rt);
      build(mid + 1, r, 2 * rt + 1);
      pushUp(rt);
    }
     
    void update(int L, int R, long long val, int l, int r, int rt) {
      if(L <= l && r <= R) {
        sum[rt] += val * (r - l + 1);
        f[rt] += val;
        return;
      }
      pushDown(l, r, rt);
      int mid = (l + r) / 2;
      if(L <= mid) update(L, R, val, l, mid, 2 * rt);
      if(R > mid) update(L, R, val, mid + 1, r, 2 * rt + 1);
      pushUp(rt);
    }
     
    long long query(int L, int R, int l, int r, int rt) {
      if(L <= l && r <= R) {
        return sum[rt];
      }
      pushDown(l, r, rt);
      int mid = (l + r) / 2;
      long long left = 0;
      long long right = 0;
      if(L <= mid) left = query(L, R, l, mid, 2 * rt);
      if(R > mid) right = query(L, R, mid + 1, r, 2 * rt + 1);
      pushUp(rt);
      return left + right;
    }
     
    int main() {
      scanf("%d%d", &n, &Q);
      build(1, n, 1);
      while(Q --) {
        char op[10];
        scanf("%s", op);
        if(op[0] == 'Q') {
          int L, R;
          scanf("%d%d", &L, &R);
          printf("%lld
    ", query(L, R, 1, n, 1));
        } else {
          int L; int R;
          long long val;
          scanf("%d%d%lld", &L, &R, &val);
          update(L, R, val, 1, n, 1);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    React中jquery引用
    实现table的单线边框的办法
    学习网站
    React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
    使用rgba设置输入框背景透明
    转: HTML5之placeholder属性以及如何更改placeholder属性中文字颜色
    转:jquery操作元素的css样式(获取、修改等等)
    购物车抛物线动画效果
    转: jquery.qrcode.js生成二维码插件&转成图片格式
    Chatbot中的填槽(Slot Filling)(转)
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8470120.html
Copyright © 2011-2022 走看看