游记 NOIP2023(public version)

游记 NOIP2023(public version)

11.17

20:30

提前一天到达考点:中山市中山纪念中学。没有看鸭子。

11.18

8:30

正式开考。然后打开了一下虚拟机,有了上一次的经验,这次直接挂好了虚拟机的共享文件夹,题目也找到在哪里了,比较顺利。写了 .vimrc。

T1 感觉比较简单,先做;T2 感觉像个什么操作逆序之后搞一下,但能做;T3 疑似有强结论,计划是做完 T1,T2 后做 T3;T4 是区间计数相关的题目,T3 搞不出来去做 T4。

9:10

一开始写的是 Trie 树,size 了一下发现竟然爆空间了,太可怕了。连续叉掉好几个做法后写了一个好写一点的,大概在 9:10 过了所有样例。

做法比较神秘,没有想到桶排(想到的时候已经不想写了),大样例跑的很快,又没有暴力拍,就丢掉了。\(O(nm\log m)\)

想了一下,这个题没有对拍的价值。

然后去写 T2。

10:30

T2 一开始是考虑能不能操作逆序以确定每个变量的最终取值,后来发现不用,直接顺着做操作,先处理出每个变量最终是固定值还是依赖于其它某个变量。很快意识到这玩意有环,于是改用扩展域并查集实现确定的过程。由于这里是游记,我也不想写题解,具体细节看看代码。(代码注释:\(2n\) 号点是一个虚点,将所有非法状态连向 \(2n\))过了大样例,不拍了。

然后玩了一下 T3,发现只会一个平方,看不出什么结论,前后缀 min/max 都试了一下好像不行,不懂。然后发现 T4 好像能做。

11:50

(记不清时间了)T4 首先显然可以 DP 的,\(O(n^2)\),观察到决策点肯定是区间的端点,离散化是必须的。然后想了一下这玩意可以直接线段树优化 DP 啊!啊?写一下,细节比较多,一个小时调了一下大概就写完了,期间因为跳过一个决策点调了一段时间的样例二。怎么切 T4 了啊?

12:30

事已至此,T3 直接写平方暴力。一开始写的 vector<vector<bool>> 编译错误,vector<vector<int>> 两秒,bool[2020][2020] + memset 0.4 秒。高估了 vector 的水平。

所以估分是 \(100+100+35+100=335\)

最后写了一个测样例的 python 程序,看着它跑完我能过的样例,然后改了一下 T3 的越界问题和 T4 没有 pushdown,然后比赛就结束了。

#!/usr/bin/python3

import os


def testsamples(name, case):
  os.system(f"g++ /media/sf_public/GD-####/{name}/{name}.cpp -o main -std=c++14 -O2 -Wall")
  # 赛后提醒:这里的考号打码
  for i in range(case):
    os.system(f"cp ./down/{name}/{name}{i + 1}.in {name}.in")
    os.system(f"time ./main")
    if os.system(f"diff ./down/{name}/{name}{i + 1}.ans {name}.out"):
      input(f"Testcase {i + 1}, Wrong Answer...")
    else :
      print(f"Accepted sample{i + 1}.")

  print(f"Problem {name}, Accepted all the samples.")

testsamples("dict", 4)
testsamples("tribool", 4)
testsamples("expand", 3)
testsamples("run", 6)

codes

点击查看代码

./dict/dict.cpp

#include <cstdio>
#include <iostream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl '\n'
#define debug(...) void(0)
#endif
typedef long long LL;
int main() {
#ifndef NF
  freopen("dict.in", "r", stdin);
  freopen("dict.out", "w", stdout);
  cin.tie(nullptr)->sync_with_stdio(0);
#endif
  int n, m;
  cin >> n >> m;
  if (n == 1) {
    cout << 1 << endl;
    return 0;
  }
  vector<string> vec(n);
  int argmin = -1, cntmin = 0;
  for (int i = 0; i < n; i++) {
    cin >> vec[i];
    string& s = vec[i];
    sort(s.begin(), s.end(), greater<char>{});
    if (argmin == -1 || s < vec[argmin]) argmin = i, cntmin = 1;
    else if (s == vec[argmin]) ++cntmin;
  }
  vector<char> ans(n);
  for (int i = 0; i < n; i++) {
    string s = vec[i];
    sort(s.begin(), s.end(), less<char>{});
    if (s < vec[argmin]) ans[i] = '1';
    else if (s == vec[argmin]) ans[i] = "01"[cntmin == 1 && argmin == i];
    else ans[i] = '0';
  }
  for (int i = 0; i < n; i++) cout << ans[i];
  cout << endl;
  return 0;
}

./expand/expand.cpp

#include <cstdio>
#include <iostream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl '\n'
#define debug(...) void(0)
#endif
typedef long long LL;
template <class T>
struct flower {
  vector<T> vec;
  flower& operator<<(const T& x) {
    vec.push_back(x);
    return *this;
  }
  int build() {
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    return vec.size();
  }
  T operator[](int i) const { return vec[i - 1]; }
  int operator()(const T& x) const {
    return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
  }
};
bool solve(vector<int> a, vector<int> b) {
  if (a[0] > b[0]) swap(a, b);
#ifdef LOCAL
  flower<int> hua;
  for (int x : a) hua << x;
  for (int x : b) hua << x;
  hua.build();
  debug("solve({");
  for (int x : a) debug("%d, ", hua(x));
  debug("}, {");
  for (int x : b) debug("%d, ", hua(x));
  debug("}\n");
#endif
  if (a[0] == b[0]) return false;
  if (a.back() >= b.back()) return false;
  int n = a.size(), m = b.size();
//vector<vector<int>> dp(n, vector<int>(m));
  static bool dp[2010][2010];
  memset(dp, false, sizeof dp);
  dp[0][0] = true;
  for (int t = 0; t <= n + m - 3; t++) {
    for (int i = 0; i <= t && i < n; i++) {
      int j = t - i;
      if (j >= m || !dp[i][j]) continue;
      if (i + 1 < n && j + 1 < m && a[i + 1] < b[j + 1])
        dp[i + 1][j + 1] = true;
      if (i + 1 < n && a[i + 1] < b[j])
        dp[i + 1][j] = true;
      if (j + 1 < m && a[i] < b[j + 1])
        dp[i][j + 1] = true;
    }
  }
  debug("finally the answer is %d\n", dp[n - 1][m - 1]);
  return dp[n - 1][m - 1];
}
int main() {
#ifndef NF
  freopen("expand.in", "r", stdin);
  freopen("expand.out", "w", stdout);
  cin.tie(nullptr)->sync_with_stdio(0);
#endif
  int C, n, m, Q;
  cin >> C >> n >> m >> Q;
  vector<int> a(n), b(m);
  for (int i = 0; i < n; i++) cin >> a[i];
  for (int j = 0; j < m; j++) cin >> b[j];
  cout << static_cast<int>(solve(a, b));
  while (Q--) {
    vector<int> c = a, d = b;
    int k1, k2;
    cin >> k1 >> k2;
    while (k1--) {
      int x, y;
      cin >> x >> y;
      c[x - 1] = y;
    }
    while (k2--) {
      int x, y;
      cin >> x >> y;
      d[x - 1] = y;
    }
    cout << static_cast<int>(solve(c, d));
  }
  cout << endl;
  return 0;
}

./run/run.cpp

#include <cstdio>
#include <iostream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl '\n'
#define debug(...) void(0)
#endif
typedef long long LL;
template <class T>
struct flower {
  vector<T> vec;
  flower& operator<<(const T& x) {
    vec.push_back(x);
    return *this;
  }
  int build() {
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    return vec.size();
  }
  T operator[](int i) const { return vec[i - 1]; }
  int operator()(const T& x) const {
    return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
  }
};
template <int N>
struct segtree {
  LL ans[N << 2], tag[N << 2];
  void maintain(int p) {
    ans[p] = max(ans[p << 1], ans[p << 1 | 1]);
  }
  void build(int p, int l, int r) {
    ans[p] = -1e18, tag[p] = 0;
    if (l == r) return ;
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
  }
  void spread(int p, LL k) {
    ans[p] += k;
    tag[p] += k;
  }
  void pushdown(int p) {
    spread(p << 1, tag[p]);
    spread(p << 1 | 1, tag[p]);
    tag[p] = 0;
  }
  void modify(int L, int R, LL k, int p, int l, int r) {
    if (L <= l && r <= R) return spread(p, k);
    int mid = (l + r) >> 1;
    pushdown(p);
    if (L <= mid) modify(L, R, k, p << 1, l, mid);
    if (mid < R) modify(L, R, k, p << 1 | 1, mid + 1, r);
    maintain(p);
  }
  LL query(int L, int R, int p, int l, int r) {
    if (L <= l && r <= R) return ans[p];
    int mid = (l + r) >> 1;
    pushdown(p);
    LL ans = -1e18;
    if (L <= mid) ans = max(ans, query(L, R, p << 1, l, mid));
    if (mid < R) ans = max(ans, query(L, R, p << 1 | 1, mid + 1, r));
    return ans;
  }
  void setValue(int x, LL k, int p, int l, int r) {
    if (l == r) return ans[p] = k, void();
    int mid = (l + r) >> 1;
    pushdown(p);
    if (x <= mid) setValue(x, k, p << 1, l, mid);
    else setValue(x, k, p << 1 | 1, mid + 1, r);
    maintain(p);
  }
};
segtree<200010> t;
vector<pair<int, int>> Lpos[200010];
int mian() {
  int n, m, k, d;
  cin >> n >> m >> k >> d;
  vector<tuple<int, int, int>> seq(m);
  flower<int> hua;
  for (int i = 0; i < m; i++) {
    int x, y, v;
    cin >> x >> y >> v;
    seq[i] = make_tuple(x - y + 1, x, v);
    hua << (x - y + 1) << x;
  }
#ifdef TEST
  for (int i = 1; i <= n; i++) hua << i;
#endif
  int cnt = hua.build();
  t.build(1, 1, cnt);
  for (int i = 1; i <= cnt; i++) Lpos[i].clear(); 
  for (auto elem : seq) {
    int l, r, v;
    tie(l, r, v) = elem;
    Lpos[hua(r)].emplace_back(hua(l), v);
  }
  LL pre = 0;
  int pos = 1;
  vector<LL> f(cnt + 1);
  for (int i = 1; i <= cnt; i++) {
    if (i > 1) t.modify(1, i - 1, -1ll * d * (hua[i] - hua[i - 1]), 1, 1, cnt);
//  pre = max(pre, f[hua(hua[i] - 1) - 1]);
//  debug("hua[%d] = %d, pre = %lld, chkmax with f[%d], which hua[] = %d\n", i, hua[i], pre, hua(hua[i] - 1) - 1, hua[hua(hua[i] - 1) - 1]);
    while (pos <= cnt && hua[pos] <= hua[i] - 2) pre = max(pre, f[pos++]);
    t.setValue(i, pre - d, 1, 1, cnt);
    for (auto elem : Lpos[i]) {
      int l, v;
      tie(l, v) = elem;
      t.modify(1, l, v, 1, 1, cnt);
    }
    f[i] = t.query(hua(hua[i] - k + 1), i, 1, 1, cnt);
    debug("f[%d] = %lld\n", hua[i], f[i]);
  }
  cout << *max_element(f.begin(), f.end()) << endl;
  return 0;
}
int main() {
#ifndef NF
  freopen("run.in", "r", stdin);
  freopen("run.out", "w", stdout);
  cin.tie(nullptr)->sync_with_stdio(0);
#endif
  int C, T;
  cin >> C >> T;
  while (T--) mian();
  return 0;
}
/*
#!/usr/bin/python3

import os


def testsamples(name, case):
  os.system(f"g++ /media/sf_public/GD-####/{name}/{name}.cpp -o main -std=c++14 -O2 -Wall")
  # 赛后提醒:这里的考号打码
  for i in range(case):
    os.system(f"cp ./down/{name}/{name}{i + 1}.in {name}.in")
    os.system(f"time ./main")
    if os.system(f"diff ./down/{name}/{name}{i + 1}.ans {name}.out"):
      input(f"Testcase {i + 1}, Wrong Answer...")
    else :
      print(f"Accepted sample{i + 1}.")

  print(f"Problem {name}, Accepted all the samples.")

testsamples("dict", 4)
testsamples("tribool", 4)
testsamples("expand", 3)
testsamples("run", 6)

*/

./tribool/tribool.cpp

#include <cstdio>
#include <iostream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl '\n'
#define debug(...) void(0)
#endif
typedef long long LL;
struct state {
  static constexpr int T = 998244353, F = 1e9 + 7, U = 1e9 + 9, NONE = 0;
  static state toState(char op) {
    switch (op) {
      case 'T' : return T;
      case 'F' : return F;
      case 'U' : return U;
    }
    return NONE;
  }
  int now;
  state() : now(NONE) {}
  state(int now) : now(now) {}
  state filp() {
    assert(now != NONE);
    if (now == T) return F;
    if (now == F) return T;
    if (now == U) return U;
    return -now;
  }
};
struct dsu {
  vector<int> fa, siz;
  explicit dsu(int n) : fa(n), siz(n, 1) { iota(fa.begin(), fa.end(), 0); }
  int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
  void merge(int x, int y) {
    debug("x = %d, y = %d\n", x, y);
    x = find(x), y = find(y);
    if (x == y) return ;
    if (siz[x] < siz[y]) swap(x, y);
    fa[y] = x;
    siz[x] += siz[y];
  }
};
int mian() {
  int n, m;
  cin >> n >> m;
  vector<state> a(n);
  for (int i = 0; i < n; i++) a[i] = i + 1;
  while (m--) {
    char op;
    int i, j;
    cin >> op >> i;
    --i;
    if (op == '+') cin >> j, --j, a[i] = a[j];
    else if (op == '-') cin >> j, --j, a[i] = a[j].filp();
    else a[i] = state::toState(op);
  }
  dsu dsy(n << 1 | 1);
  for (int i = 0; i < n; i++) {
    debug("i = %d, a[%d] = %d\n", i, i, a[i].now);
    int j = abs(a[i].now) - 1;
    assert(a[i].now != state::NONE);
    if (a[i].now == -(i + 1)) a[i] = state::U;
    if (a[i].now == state::T) dsy.merge(i << 1, n << 1);
    else if (a[i].now == state::F) dsy.merge(i << 1 | 1, n << 1);
    else if (a[i].now == state::U) dsy.merge(i << 1, i << 1 | 1);
    else if (a[i].now < 0) dsy.merge(i << 1, j << 1 | 1), dsy.merge(i << 1 | 1, j << 1);
    else dsy.merge(i << 1, j << 1), dsy.merge(i << 1 | 1, j << 1 | 1);
  }
  for (int i = 0; i < n; i++) if (dsy.find(i << 1) == dsy.find(i << 1 | 1)) dsy.merge(i << 1, n << 1);
  vector<int> vis(n << 1 | 1, 0);
  int ret = 0;
  for (int i = 0; i < n; i++) {
    if (!vis[dsy.find(i << 1)]) {
      if (dsy.find(i << 1) == dsy.find(n << 1)) vis[dsy.find(i << 1)] = -1;
      else ret += dsy.siz[dsy.find(i << 1)], vis[dsy.find(i << 1)] = 1, vis[dsy.find(i << 1 | 1)] = -1;
    }
    if (vis[dsy.find(i << 1)] == -1 && !vis[dsy.find(i << 1 | 1)]) {
      if (dsy.find(i << 1 | 1) == dsy.find(n << 1)) vis[dsy.find(i << 1 | 1)] = -1;
      else ret += dsy.siz[dsy.find(i << 1 | 1)], vis[dsy.find(i << 1 | 1)] = 1;
    }
  }
  cout << n - ret << endl;
  return 0;
}
int main() {
#ifndef NF
  freopen("tribool.in", "r", stdin);
  freopen("tribool.out", "w", stdout);
  cin.tie(nullptr)->sync_with_stdio(0);
#endif
  int T, C;
  cin >> C >> T;
  while (T--) mian();
  return 0;
}
//10:34

posted @ 2023-11-19 10:27  caijianhong  阅读(203)  评论(0编辑  收藏  举报