首页 > 其他分享 >[ARC133B] Dividing Subsequence

[ARC133B] Dividing Subsequence

时间:2024-02-21 21:12:37浏览次数:38  
标签:Dividing int ARC133B Subsequence 序列 本题 define

Dividing Subsequence

这道题与最长公共子序列类似,可以先去水一水那道题。

题意

本题就是让你从 \(p\) 里面选出一个子序列 \(b_i\) 和 \(q\) 里面选出一个子序列 \(a_i\),我们要使 \(b_i\) 是 \(a_i\) 的倍数。

解法

本题直接用动态规划,是 \(O(n^2)\) 做法,会超时,因此我们用树状数组维护区间最值来进行优化,那么本题与最长上升子序列的解法类似——因为我们求了前面的可以求后面的,但是求了后面的就不能求前面的了,而且还要求最长,因此是一个最长上升子序列问题。注意对于 \(p_i\) 更新 \(q_i\) 时要从大到小。

解释很多在代码上,请看代码:

代码

// Problem: [ARC133B] Dividing Subsequence
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/AT_arc133_b
// Memory Limit: 1 MB
// Time Limit: 5000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

#define lowbit(x) x & -x
#define pb push_back
#define all(x) x.begin(), x.end()
#define fst ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

typedef long long ll;

const ll N = 1e6 + 10;

int n;     // n个元素
int a[N];  // p数组的每个元素
int b[N];  // q数组的每个元素
int c[N];  // c[]表示i元素在q数组中的位置

vector<int> v[N];  //存储i元素所有的倍数位置
int d[N];
void update(int x, int v) {
  while (x <= n) {
    d[x] = max(d[x], v);
    x += lowbit(x);
  }
}
int query(int x) {
  int res = 0;
  while (x) {
    res = max(d[x], res);
    x -= lowbit(x);
  }
  return res;
}

int main() {
  fst;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  // 3 1 4 2
  // 2 4 1 3
  for (int i = 1; i <= n; i++) {
    cin >> b[i];
    c[b[i]] = i;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = i; j <= n; j += i) {
      //对于i元素,i的倍数是j
      v[i].pb(c[j]);
    }
  }
  for (int i = 1; i <= n; i++) {
    //目标维护a[i]的所有倍数出现的位置
    //对这个位置进行降序排列
    int t = a[i];
    sort(all(v[t]));
    reverse(all(v[t]));
    //就是求这个的最长上升子序列
    for (auto e : v[t]) {
      //对于e元素来说,求来的比我早的,且数值比我小的最大值
      int tmp = query(e - 1);
      update(e, tmp + 1);
    }
  }
  cout << query(n) << endl;
  return 0;
}

本题就愉快地结束了。

标签:Dividing,int,ARC133B,Subsequence,序列,本题,define
From: https://www.cnblogs.com/gongyuchen/p/18026220

相关文章

  • CF1922E Increasing Subsequences 题解
    解题思路因为可以有空集,那么我们首先构造第一段最长的连续上升的序列,那么这段序列中共有\(2^{\mids\mid}\)个上升子序列。接下来我们考虑补全剩余的,我们不妨将剩余的部分全部设为连续不增序列,那么设当前位置在第一段中有\(k\)个小于它的,那么添加这个数后可以增加\(2^{k-1}......
  • CF1924D Balanced Subsequences
    题意简述有\(n\)个左括号和\(m\)个右括号,求最长合法括号子序列长度为\(2k\)的括号序列的数量,对\(10^9+7\)取模。多组数据。\(T\le3\times10^3,n,m,k\le2\times10^3\)分析可能需要的前置知识:如何求一个字符串的最长合法括号子序列?维护一个括号栈,若遇到左括号则直接......
  • CodeForces 1924D Balanced Subsequences
    洛谷传送门CF传送门发现去掉匹配的\(2k\)个括号后,剩下的串一定形如\())\ldots)((\ldots(\),其中右括号数量为\(a=m-k\),左括号数量为\(b=n-k\)。考虑把剩下的串像\())\ldots)\mid((\ldots(\)一样分成两半。枚举左半边加入了\(\frac{i}{2}\)对匹配,则......
  • B - Arithmetic Progression Subsequence
    B-ArithmeticProgressionSubsequenceProblemStatementYouaregivenasequence$A$oflength$N$consistingofintegersbetween$1$and$\textbf{10}$,inclusive.Apairofintegers$(l,r)$satisfying$1\leql\leqr\leqN$iscalledagoodpairif......
  • Largest Subsequence
    操作:选取词性最大的子序列,向右循环一次问你进行多少次这样的操作能使数组有序,如果不能就输出-1思路:首先要知道的是一个词性最大的序列整个右移过后,数组的新词性最大的序列就是之前的词性最大序列去了最后一个字母.找出词性最大的子序列intn; strings......
  • [ABC271E] Subsequence Path 题解
    [ABC271E]SubsequencePath题解思路解析很好的一道题,很有迷惑性,表面上是一道图论实际上是dp,定义\(f_{i}\)为从\(1\)到\(i\)的最短“好路”。先把每条边对应的起点,终点和边权记录下来,然后输入每个\(e\),由于是子序列顺序不会改变,因此可以顺序进行操作。对于每一个\(e......
  • CF1621G Weighted Increasing Subsequences
    CF1621GWeightedIncreasingSubsequences你有一个长度为\(n\)的序列,定义\(a\)的一个长度为\(k\)的子序列为\(a_{i_1},a_{i_2},\dots,a_{i_k}\)。由此,我们不难发现,\(a\)的一个长度为\(k\)的子序列为上升子序列,当且仅当\(\forallj\in[1,k)\),\(a_{i_j}<a_{i_{j+1}}\)......
  • [Codeforces] CF1817A Almost Increasing Subsequence
    CF1817AAlmostIncreasingSubsequence题意给定长度为\(n\)一个序列\(a\)以及\(q\)次询问,每次询问给出\(l\)和\(r\),找出序列\(a\)在\([l,r]\)内最长的几乎递增子序列。对于几乎递增的定义:如果一个序列中不存在连续的三个数\(x\),\(y\),\(z\),使得\(x\gey\ge\......
  • [ARC133B] Dividing Subsequence
    DividingSubsequence这道题与最长公共子序列类似,可以先去水一水那道题。题意本题就是让你从\(p\)里面选出一个子序列\(b_i\)和\(q\)里面选出一个子序列\(a_i\),我们要使\(b_i\)是\(a_i\)的倍数。解法本题直接用动态规划,是\(O(n^2)\)做法,会超时,因此我们用树状数......
  • [CF83E] Two Subsequences 题解
    [CF83E]TwoSubsequences题解思路定义\(overlap(a,b)\)为字符串\(a\)的后缀与\(b\)的前缀的最大相等的长度,有\(|f(a,b)|=|a|+|b|-overlap(a,b)\),下文称匹配为相邻两串的\(overlap\)。观察到每次操作之后,一定有一个序列是以\(a_i\)为结尾的。所以根据这个......