首页 > 其他分享 >[洛谷 P3481] [BZOJ1118] [POI2009] PRZ-Algorithm Speedup

[洛谷 P3481] [BZOJ1118] [POI2009] PRZ-Algorithm Speedup

时间:2023-11-07 17:44:05浏览次数:39  
标签:cnt POI2009 Algorithm get int stk buc 洛谷 ord

题目描述

你需要计算一个函数 \(F(x, y)\),其中 \(x, y\) 是两个正整数序列。

bool F(std::vector<int> x, std::vector<int> y) {
  if (W(x).size() != W(y).size()) return false;
  if (W(x).size() == 1) return true;
  return F(p(x), p(y)) && F(s(x), s(y));
}

\(W(x)\) 表示序列 \(x\) 的不同元素组成的集合。

\(p(x)\) 表示序列 \(x\) 的最长前缀满足 \(W(p(x)) \neq W(x)\)。

\(s(x)\) 表示序列 \(x\) 的最长后缀满足 \(W(s(x)) \neq W(x)\)。

输入格式

第一行一个正整数 \(T\) 表示数据组数。

对于每组数据:

第一行两个正整数 \(n, m\) 分别表示序列 \(x\) 的长度和序列 \(y\) 的长度。

第二行 \(n\) 个正整数,其中第 \(i\) 个表示 \(x_i\)。

第三行 \(m\) 个正整数,其中第 \(i\) 个表示 \(y_i\)。

输出格式

输出 \(T\) 行,对于每组数据,若 \(F(x, y)\) 为真输出 \(1\),否则输出 \(0\)。

数据范围

\(1 \le T \le 13\),\(1 \le n, m \le 10^5\),\(1 \le x_i, y_i \le 100\)。

题解

下文中用 \(x[l.. r]\) 表示序列 \(x\) 的第 \(l\) 个元素到第 \(r\) 个元素组成的子串。

考察 \(x, y\) 中的哪些子串会在计算 \(F(x, y)\) 的过程中会被遍历到。

以 \(x\) 为例,被遍历到的子串 \(x[l.. r]\) 必然满足 \((l = 1 \lor x_{l - 1} \not \in x[l.. r]) \land (r = n \lor x_{r + 1} \not \in x[l.. r])\)。

容易发现当 \(|W(x[l..r])|\) 固定时,只有不超过 \(n\) 个子串会被遍历到,因此总子串个数不超过 \(n \max x_i\)。

当 \(|W(x[l..r])|\) 固定时,枚举 \(r\),不难发现只有至多一个 \(l\) 满足 \(l = 1 \lor x_{l - 1} \not \in x[l..r]\),因此有不超过 \(n\) 个会被遍历到的子串。

不难对 \(|W(x)|\) 归纳证明 \(F(x, y) \land F(y, z) \rightarrow F(x, z)\),因此 \(F\) 代表一个等价关系。

kczno1 的题解 就此给出了哈希的思路:

既然是等价关系,考虑设计哈希函数 \(h(x)\),使得 \(F(x, y) \approx [h(x) = h(y)]\)。

\(h(x)\) 需要包含 \(h(p(x)), h(s(x)), W(x)\) 这三个信息。由于 \(h(s(x))\) 已经包含了 \(W(s(x))\),因此 \(h(x)\) 所需要包含的 \(W(x)\) 可以简化为大小为 \(1\) 的集合 \(W(x) - W(s(x))\)。

按 \(|W(x[l..r])|\) 从小到大转移,该算法可以做到时间复杂度 \(O(n \max x_i)\)。

但毛估估一下这相当于哈希一个长度为指数级的序列,正确率堪忧,也确实无法通过。

POI 官解 的做法类似后缀数组的倍增求法,对 \(x, y\) 可能遍历到的子串按照 \(W\) 分层从小到大进行正整数哈希。

这个做法基于每一层的哈希函数的求解只会依赖上一层的哈希函数的事实。

\(h(x[l..r])\) 相当于正整数三元组 \((h(p(x)), h(s(x)), W(x) - W(s(x)))\),我们把同层的 \(x, y\) 的子串对应的三元组取出,用基数排序进行离散化,把三元组变为正整数。

时间复杂度 \(O(n \max x_i)\),并且没有正确率问题。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using i128 = __int128;
using u128 = unsigned __int128;
template <typename T>
void chkmax(T &x, const T &y) {
  if (x < y) x = y;
}
template <typename T>
void chkmin(T &x, const T &y) {
  if (y < x) x = y;
}
constexpr int MAXN = 1e5 + 10, MAXVAL = 105;
int n[2], a[2][MAXN], dpl[2][2][MAXN], dpr[2][2][MAXN], p, sz, tp;
tuple<int, int, int, int *, int *> stk[MAXN * 2];
void ins(int t, int k) {
  static int cnt[MAXVAL], num;
  num = 0;
  memset(cnt, 0, sizeof(cnt));
  for (int i = 1, j = 1; i <= n[t]; ++i) {
    num += !(cnt[a[t][i]]++);
    while (num > k) num -= !(--cnt[a[t][j++]]);
    if (num == k && (i == n[t] || !cnt[a[t][i + 1]])) {
      stk[++tp] = {dpr[!p][t][j], dpl[!p][t][i], 0, &dpr[p][t][j],
                   &dpl[p][t][i]};
      while (num == k) num -= !(--cnt[a[t][j++]]);
      get<2>(stk[tp]) = a[t][j - 1];
    }
  }
}
void rsort() {
  static int buc[MAXN * 2], ord[MAXN * 2], tord[MAXN * 2];
  fill(buc + 1, buc + MAXVAL, 0);
  for (int i = 1; i <= tp; ++i) ++buc[get<2>(stk[i])];
  for (int i = 2; i < MAXVAL; ++i) buc[i] += buc[i - 1];
  for (int i = 1; i <= tp; ++i) ord[buc[get<2>(stk[i])]--] = i;
  fill(buc + 1, buc + sz + 1, 0);
  for (int i = 1; i <= tp; ++i) ++buc[get<1>(stk[i])];
  for (int i = 2; i <= sz; ++i) buc[i] += buc[i - 1];
  for (int i = tp; i >= 1; --i) tord[buc[get<1>(stk[ord[i]])]--] = ord[i];
  fill(buc + 1, buc + sz + 1, 0);
  for (int i = 1; i <= tp; ++i) ++buc[get<0>(stk[i])];
  for (int i = 2; i <= sz; ++i) buc[i] += buc[i - 1];
  for (int i = tp; i >= 1; --i) ord[buc[get<0>(stk[tord[i]])]--] = tord[i];
  *get<3>(stk[ord[1]]) = *get<4>(stk[ord[1]]) = sz = 1;
  for (int i = 2; i <= tp; ++i) {
    *get<3>(stk[ord[i]]) = *get<4>(stk[ord[i]]) =
        (get<0>(stk[ord[i]]) == get<0>(stk[ord[i - 1]]) &&
                 get<1>(stk[ord[i]]) == get<1>(stk[ord[i - 1]]) &&
                 get<2>(stk[ord[i]]) == get<2>(stk[ord[i - 1]])
             ? sz
             : ++sz);
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int cas;
  cin >> cas;
  while (cas--) {
    cin >> n[0] >> n[1];
    static int cnt[2][MAXVAL];
    memset(cnt, 0, sizeof(cnt));
    for (int t = 0; t < 2; ++t) {
      for (int i = 1; i <= n[t]; ++i) {
        cin >> a[t][i];
        ++cnt[t][a[t][i]];
      }
    }
    if (!equal(cnt[0], cnt[0] + MAXVAL, cnt[1],
               [](int x, int y) { return (bool)x == (bool)y; })) {
      cout << "0\n";
      continue;
    }
    int num = count_if(cnt[0], cnt[0] + MAXVAL, [](int x) { return x; });
    if (num == 1) {
      cout << "1\n";
      continue;
    }
    for (int t = 0; t < 2; ++t) {
      copy(a[t] + 1, a[t] + n[t] + 1, dpl[0][t] + 1);
      copy(a[t] + 1, a[t] + n[t] + 1, dpr[0][t] + 1);
    }
    sz = MAXVAL - 1;
    p = 0;
    for (int k = 2; k <= num; ++k) {
      p ^= 1;
      tp = 0;
      ins(0, k);
      ins(1, k);
      memset(dpl[p], 0, sizeof(dpl[p]));
      memset(dpr[p], 0, sizeof(dpr[p]));
      rsort();
    }
    cout << (dpr[p][0][1] == dpr[p][1][1]) << "\n";
  }
  return 0;
}
/*
g++ PRZ.cpp -o PRZ -std=c++14 -O2 -Wall -Wextra -Wshadow -g
-fsanitize=address,undefined
*/

标签:cnt,POI2009,Algorithm,get,int,stk,buc,洛谷,ord
From: https://www.cnblogs.com/JCY-std/p/17815520.html

相关文章

  • JSch连接SSH问题Exception:Algorithm negotiation fail
    Java连接RPA系统,由于特殊原因不能使用接口,决定用openssh连接,定时读取与推送。注意点:1、C:\ProgramData\ssh\sshd_config配置2、ssh-keygen-trsa生成秘钥方式3、生成之后追加到authorized_keys编码格式utf-84、authorized_keys后缀5、com.jcraft.jsch长时间没有更新,windo......
  • 【洛谷 P1046】[NOIP2005 普及组] 陶陶摘苹果 题解(比较)
    [NOIP2005普及组]陶陶摘苹果题目描述陶陶家的院子里有一棵苹果树,每到秋天树上就会结出个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现在已知个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的......
  • 【洛谷 P1909】[NOIP2016 普及组] 买铅笔 题解(打擂台法)
    [NOIP2016普及组]买铅笔题目背景NOIP2016普及组T1题目描述P老师需要去商店买支铅笔作为小朋友们参加NOIP的礼物。她发现商店一共有种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。为了公平起见,P老师决定只买同一种包装的铅笔。商店不允许将铅笔的包装......
  • 【LGR-161-Div.3】洛谷基础赛 #4 P9688 Colo.
    原题链接:P9688Colo.很显然,能够共存的颜色一定不会相交,所以可以记录每个颜色最左边的位置和最右边的位置,我们对于每个颜色只考虑,这个颜色左边的可以和这个颜色共存的额颜色用f[i][j]表示当前考虑i这种颜色,选i这种颜色,然后在i这种颜色之前(包括这种颜色)一共选了j种颜色的最大价值......
  • 【洛谷 P1085】[NOIP2004 普及组] 不高兴的津津 题解(打擂台法)
    [NOIP2004普及组]不高兴的津津题目描述津津上初中了。妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班。另外每周妈妈还会送她去学习朗诵、舞蹈和钢琴。但是津津如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。假设津津不会因......
  • Proj. Unknown: Deciding Differential Privacy of Online Algorithms with Multiple
    Paperhttps://arxiv.org/abs/2309.06615Abstract背景:自动机A被称作查分隐私自动机:当对某些D,对任何隐私预算ε>0,该自动机是Dε-differentiallyprivate(ADiPautomatonisaparametricautomatonwhosebehaviordependsontheprivacybudget......
  • Princeton Algorithms, Part I week2 stack&queue
    stack:先进后出queue:先进先出首先是stack有两种实现方式,第一种是用链表,第二种是用数组。Stack:linked-listrepresentation   stack:arrayimplementation  上面这个实现是固定长度的arrayimplementation非常不方便,所以引入可变长度的实现resizing-array......
  • 基于rk3588----i2c驱动框架学习(2)-总线驱动 algorithm 分析
    rk3588i2calgorithm分析来了来了,上次分析完i2c的驱动框架今天我们就看看i2c的algorithm是如何实现的staticconststructi2c_algorithmrk3x_i2c_algorithm={.master_xfer=rk3x_i2c_xfer,.master_xfer_atomic......
  • 洛谷P5707 【深基2.例12】上学迟到(Python 3)
    题。审题:1.yyy要花十分钟垃圾分类!不要忘了在总分钟数上加102.如果时或分为个位数,则需要用0在前补位 思路:先把总共需要的分钟数算出来,然后求时和分。如果时大于8,那么再补上24,用来使时间符合格式。 关键点:1.补位:print('%02d'%m),具体看这篇2.注意当分钟数恰好为60倍数的......
  • (C语言)1到50的阶乘之和列表,参考用,洛谷:P1009 [NOIP1998 普及组] 阶乘之和
    1到50列表,阶乘之和S=1!+2!+3!+⋯+n!(n≤50)1::12::33::94::335::1536::8737::59138::462339::40911310::403791311::4395471312::52295631313::674997711314::9392826831315::140160263631316::2232439252431317::37801182062031318::678038552634831319::12842......