zoukankan      html  css  js  c++  java
  • 洛谷提高模拟赛2

    比赛链接 ()[https://www.luogu.org/contestnew/show/11251]

    T1

    捕获7.PNG

    显然排序后每一个豆子都在上一个的右下角
    排序后组合数统计步数就可以了

    知识点补充:组合数统计步数 在dx+dy步中 选dx步向下走 其余向右走

    标程

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 200005;
    const int MOD = (int)1e9 + 7;
    
    int n, m, k, fac[MAXN], inv[MAXN];
    
    struct Point {
      int x, y;
      bool operator<(const Point & rhs) const {
        return x + y < rhs.x + rhs.y;
      }
    }P[MAXN];
    
    int fexp(int x, int y) {
      int res = 1;
      for(int i = 1; i <= y; i <<= 1) {
        if(i & y) res = 1LL * res * x % MOD;
        x = 1LL * x * x % MOD;
      }
      return res;
    }
    
    void init(int n) {
      fac[0] = inv[0] = 1;
      for(int i = 1; i <= n; i++) {
        fac[i] = 1LL * fac[i - 1] * i % MOD;
        inv[i] = fexp(fac[i], MOD - 2);
      }
    }
    
    int C(int n, int m) {
      assert(n >= m);
      return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    
    int main() {
      scanf("%d %d %d", &n, &m, &k);
      init(200000);
      for(int i = 1; i <= k; i++) {
        scanf("%d %d", &P[i].x, &P[i].y);
      }
      P[++k] = Point{1, 1};
      P[++k] = Point{n, m};
      sort(P + 1, P + k + 1);
      int ans = 1;
      for(int i = 2; i <= k; i++) {
        int dx = P[i].x - P[i - 1].x;
        int dy = P[i].y - P[i - 1].y;
        if(dx < 0 || dy < 0) {
          ans = 0;
          break;
        }
        ans = 1LL * ans * C(dx + dy, dx) % MOD;
      }
      printf("%d
    ", ans);
      return 0;
    }
    

    T2

    捕获7.PNG

    想到了统计不满足的 但是没有解决重叠问题
    正解:树链剖分扫描线
    子树dfn连续嘛

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 300005;
    
    int n, k;
    vector<int> G[MAXN];
    
    int dfs_clock, deep[MAXN], fa[MAXN], size[MAXN];
    int son[MAXN], top[MAXN], dfn[MAXN], dfm[MAXN], low[MAXN];
    
    void dfs1(int cur, int father, int depth) {
      size[cur] = 1;
      fa[cur] = father;
      deep[cur] = depth;
      son[cur] = 0;
      for(int i = 0; i < G[cur].size(); i++) {
        int nx = G[cur][i];
        if(nx != father) {
          dfs1(nx, cur, depth + 1);
          size[cur] += size[nx];
          if(size[nx] > size[son[cur]]) {
            son[cur] = nx;
          }
        }
      }
    }
    
    void dfs2(int cur, int tp) {
      top[cur] = tp;
      dfn[cur] = ++dfs_clock;
      dfm[dfs_clock] = cur;
      if(son[cur]) dfs2(son[cur], tp);
      for(int i = 0; i < G[cur].size(); i++) {
        int nx = G[cur][i];
        if(nx != fa[cur] && nx != son[cur]) {
          dfs2(nx, nx);
        }
      }
      low[cur] = dfs_clock;
    }
    
    int lca(int x, int y) {
      int t1 = top[x], t2 = top[y];
      while(t1 != t2) {
        if(deep[t1] < deep[t2]) {
          swap(x, y); swap(t1, t2);  
        }
        x = fa[t1], t1 = top[x];
      }
      return deep[x] < deep[y] ? x : y;
    }
    
    int getAnc(int x, int depth) {
      while(deep[top[x]] > depth) x = fa[top[x]];
      return dfm[dfn[top[x]] + depth - deep[top[x]]];
    }
    
    struct Node {
      pair<int, int> val;
      int tag;
      Node *ls, *rs;
      void pushUp() {
        if(ls->val.first == rs->val.first) {
          val = make_pair(ls->val.first, ls->val.second + rs->val.second);
        } else {
          val = min(ls->val, rs->val);
        }
      }
      void update(int t) {
        val.first += t;
        tag += t;
      }
      void pushDown() {
        if(tag) {
          ls->update(tag);
          rs->update(tag);
          tag = 0;
        }
      }
    }pool[MAXN<<1];
    
    Node *newNode() {
      static int cnt = 0;
      return &pool[cnt++];
    }
    
    Node *build(int l, int r) {
      Node *cur = newNode();
      if(l < r) {
        int mid = (l + r) / 2;
        cur->ls = build(l, mid);
        cur->rs = build(mid + 1, r);
        cur->pushUp();
      } else {
        cur->val = make_pair(0, 1);
        cur->tag = 0;
      }
      return cur;
    }
    
    void add(Node *cur, int l, int r, int a, int b, int v) {
      if(a <= l && b >= r) {
        cur->update(v);
      } else {
        cur->pushDown();
        int mid = (l + r) / 2;
        if(a <= mid) add(cur->ls, l, mid, a, b, v);
        if(b > mid) add(cur->rs, mid + 1, r, a, b, v);
        cur->pushUp();
      }
    }
    
    pair<int, int> query(Node *cur, int l, int r, int a, int b) {
      if(a <= l && b >= r) {
        return cur->val;
      } else {
        int mid = (l + r) / 2;
        cur->pushDown();
        pair<int, int> ls = make_pair(INT_MAX, INT_MAX);
        pair<int, int> rs = make_pair(INT_MAX, INT_MAX);
        if(a <= mid) ls = query(cur->ls, l, mid, a, b);
        if(b > mid) rs = query(cur->rs, mid + 1, r, a, b);
        if(ls.first == rs.first) {
          return make_pair(ls.first, ls.second + rs.second);
        } else {
          return min(ls, rs);
        }
      }
    }
    
    struct Info {
      int y1, y2, v;
    };
    
    vector<Info> vec[MAXN];
    
    void add(int x1, int x2, int y1, int y2, int v) {
      vec[x1].push_back(Info{y1, y2, v});
      vec[x2 + 1].push_back(Info{y1, y2, -v});
    }
    
    void add(int x, int y, int v) {
      int z = lca(x, y);
      if(z != x && z != y) {
        add(dfn[x], low[x], dfn[y], low[y], v);
        add(dfn[y], low[y], dfn[x], low[x], v);
      } else {
        if(y == z) swap(x, y);
        // x is the lca(x, y);
        x = getAnc(y, deep[x] + 1);
        if(dfn[x] > 1) {
          add(dfn[y], low[y], 1, dfn[x] - 1, v);
          add(1, dfn[x] - 1, dfn[y], low[y], v);
        }
        if(low[x] < n) {
          add(dfn[y], low[y], low[x] + 1, n, v);
          add(low[x] + 1, n, dfn[y], low[y], v);
        }
      }
    }
    
    int main() {
      scanf("%d %d", &n, &k);
      vector<pair<int, int> > E;
      for(int i = 1; i < n; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        E.push_back(make_pair(x, y));
        G[x].push_back(y);
        G[y].push_back(x);
      }
      dfs1(1, 0, 1); dfs2(1, 1);
      for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= min(n, i + k); j++) {
          add(i, j, 1);
        }
      }
      long long ans = 0;
      Node *root = build(1, n);
      for(int i = 1; i <= n; i++) {
        for(int j = 0; j < vec[i].size(); j++) {
          Info cur = vec[i][j];
          add(root, 1, n, cur.y1, cur.y2, cur.v);
        }
        pair<int, int> cur = root->val;
        if(cur.first == 0) {
          ans += cur.second;
        }
      }
      printf("%lld
    ", (ans + n) / 2);
      return 0;
    }
    
    

    T3

    捕获7.PNG

    有一个奇妙的思路
    计算每一个b[i]与对应a[i]的位置差绝对值之和tot
    然后找到最大的i使得2*(i - 1)是tot的约数且i不大于n

    然鹅爆零

    出题者本意是要练大家打表找规律。。。
    注:要学会用程序打表哦 【吐血

    不知道题目给出操作是什么效果时 打表吧

    部分分:循环同构 kmp

    知识点补充:即在s1后续一个s1 然后拿s2在里面kmp

    一堆大讨论。。。
    n是奇数:ans = n - 1
    n是偶数:
    数列是排列且逆序对有偶数个 ans = n - 2
    数列是排列且逆序对有奇数个 ans = n - 1
    有重复 ans = n - 1

    打表及标程如下

    //打表
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    int solve(int n, int k) {
      string s;
      for(int i = 1; i <= n; i++) {
        s += (char)(i + '0');
      }
      queue<string> Q;
      map<string, int> vis;
      Q.push(s);
      vis[s] = 1;
      while(!Q.empty()) {
        string cur = Q.front(); Q.pop();
        for(int i = 0; i < cur.size(); i++) {
          // [i, i + k - 1]
          if(i + k - 1 >= cur.size()) break;
          string nx = cur;
          for(int j = i + k - 1; j > i; j--) {
            swap(nx[j], nx[j - 1]);
          }
          if(!vis[nx]) {
            Q.push(nx);
            vis[nx] = 1;
          }
        }
      }
      return vis.size();
    }
    
    int main() {
      int n = 9;
      for(int k = 2; k <= 9; k++) {
        cerr << solve(n, k) << endl;
      }
      return 0;
    }
    
    //标程:
    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    bool checkNull(const vector<int> & a, const vector<int> & b) {
      vector<int> A(a), B(b);
      sort(A.begin(), A.end());
      sort(B.begin(), B.end());
      return A != B;
    }
    
    int circularMin(const vector<int> & a) {
      int n = a.size();
      vector<int> s(a.size() + a.size());
      for(int i = 0; i < s.size(); i++) {
        s[i] = a[i % a.size()];
      }
      int i = 0, j = 1, k;
      while(i < n && j < n) {
        for(k = 0; s[i + k] == s[j + k]; k++);
        if(k >= n) break;
        if(s[i + k] > s[j + k]) i += k + 1;
        else j += k + 1;
        if(i == j) j++;
      }
      return i < j ? i : j;
    }
    
    bool checkN(const vector<int> & a, const vector<int> & b) {
      int p1 = circularMin(a);
      int p2 = circularMin(b);
      for(int i = 0; i < a.size(); i++) {
        if(a[p1] != b[p2]) return false;
        p1 = (p1 + 1) % a.size();
        p2 = (p2 + 1) % a.size();
      }
      return true;
    }
    
    bool checkUnique(const vector<int> & a) {
      vector<int> A(a);
      for(int i = 1; i < A.size(); i++) {
        if(A[i] == A[i - 1]) return false;
      }
      return true;
    }
    
    ll calc(const vector<int> & a) {
      int n = a.size();
      vector<int> p(a);
      sort(p.begin(), p.end());
      p.erase(unique(p.begin(), p.end()), p.end());
      vector<int> A(n);
      for(int i = 0; i < n; i++) {
        A[i] = lower_bound(p.begin(), p.end(), a[i]) - p.begin() + 1;
      }
      vector<int> c(n + 1);
      auto sum = [&](int x) {
        int ret = 0;
        for(; x >= 1; x -= x & -x) ret += c[x];
        return ret;
      };
      auto add = [&](int x, int y) {
        for(; x <= n; x += x & -x) c[x] += y;
      };
      ll res = 0;
      for(int i = n - 1; i >= 0; i--) {
        res += sum(A[i] - 1);
        add(A[i], 1);
      }
      return res;
    }
    
    int main() {
      int T;
      cin >> T;
      while(T--) {
        int n;
        cin >> n;
        vector<int> a(n), b(n);
        for(int i = 0; i < n; i++) cin >> a[i];
        for(int i = 0; i < n; i++) cin >> b[i];
        if(checkNull(a, b)) {
          cout << -1 << endl;
        } else if(checkN(a, b)) {
          cout << n << endl;
        } else {
          if(n % 2 == 0 && checkUnique(a)) {
            int p1 = calc(a) % 2;
            int p2 = calc(b) % 2;
            if(p1 == p2) {
              cout << n - 1 << endl;
            } else {
              cout << n - 2 << endl;
            }
          } else {
            cout << n - 1 << endl;
          }
        }
      }
      return 0;
    }
    

    附赠万能头 #include <bits/stdc++.h>

  • 相关阅读:
    [R] read.table的check.names参数防止读入数据时列名前自动加上"X."
    【宏基因组】MEGAN4,MEGAN5和MEGAN6的Linux安装和使用
    洛谷—— P1077 摆花
    洛谷—— P2733 家的范围 Home on the Range
    BZOJ——T 1801: [Ahoi2009]chess 中国象棋
    洛谷—— P1379 八数码难题
    BZOJ——T 1800: [Ahoi2009]fly 飞行棋
    几种outofmemory
    几种常见web攻击手段及其防御方式
    JVM参数
  • 原文地址:https://www.cnblogs.com/hjmmm/p/9786442.html
Copyright © 2011-2022 走看看