洛谷提高模拟赛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\n", 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\n", (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>

posted @ 2018-10-14 15:19  hjmmm  阅读(177)  评论(0编辑  收藏  举报