首页 > 其他分享 >CF 1801 C

CF 1801 C

时间:2024-09-15 23:02:34浏览次数:1  
标签:le limits 1801 int Max CF max id

题目描述

有 \(N\) 个专辑,第 \(i\) 个专辑中有 \(k_i\) 首歌曲,其中第 \(j\) 首歌的酷炫程度为 \(a_{i,j}\)。

你会选择一个排列 \(p_1,p_2,\dots,p_N\),每次你会将 \(p_i\) 中所有歌曲从前往后依次听完。每当你遇到一个严格大于之前听过所有歌曲的歌曲,则你会对这个歌曲产生印象。

求最多能有多少个令你产生印象的歌曲。

思路

考虑贪心地求解。

很容易想到这样一种贪心:按每个专辑的最大值从小到大排序,然后做 dp。

但是不是对的呢?假设我们其中有一个专辑 \(i\) 不是从小到大排序的,即 \(\max\limits_{j=1}^{k_i} \{a_{i,j}\}>\max\limits_{j=1}^{k_{i+1}} \{a_{i+1,j}\}\),那么此时 \(i,i+1\) 都无法互相转移。但将 \(i,i+1\) 交换,它才有可能转移。而多一些转移一定不会使答案更劣,所以此贪心正确。

dp 使用树状数组优化即可。

这里清空要注意不能每次把整个树状数组清空,而要记录被修改过的位置进行清空。

空间复杂度 \(O(N+\max \limits_{1\le i\le N,1\le j \le k_i}\{a_{i,j}\} + \sum \limits_{i=1}^N k_i \log \max \limits_{1\le i\le N,1\le j \le k_i}\{a_{i,j}\})\),时间复杂度 \(O(N\log N + \sum \limits_{i=1}^N k_i \log \max \limits_{1\le i\le N,1\le j \le k_i}\{a_{i,j}\})\)。

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 200001, MAXV = 200002;

int t, n, id[MAXN], Max[MAXN], tr[MAXV];
vector<int> a[MAXN], pos;

int lowbit(int x) {
  return x & -x;
}

void update(int p, int x) {
  p++;
  for(; p < MAXV; tr[p] = max(x, tr[p]), pos.push_back(p), p += lowbit(p)) {
  }
}

int Getmax(int p) {
  p++;
  int Max = 0;
  for(; p; Max = max(Max, tr[p]), p -= lowbit(p)) {
  }
  return Max;
}

void Solve() {
  cin >> n;
  pos.clear();
  for(int i = 1, k; i <= n; ++i) {
    cin >> k;
    id[i] = i;
    Max[i] = 0;
    a[i].clear();
    a[i].resize(k + 1);
    for(int j = 1; j <= k; ++j) {
      cin >> a[i][j];
      Max[i] = max(Max[i], a[i][j]);
    }
  }
  sort(id + 1, id + n + 1, [](const int &a, const int &b) {
    return Max[a] < Max[b];
  });
  for(int i = 1; i <= n; ++i) {
    int maxx = 0, res = 0;
    for(int j = 1; j < int(a[id[i]].size()); ++j) {
      if(a[id[i]][j] > maxx) {
        res = max(res, Getmax(a[id[i]][j] - 1)) + 1;
        maxx = a[id[i]][j];
      }
    }
    update(Max[id[i]], res);
  }
  cout << Getmax(MAXV - 2) << "\n";
  pos.erase(unique(pos.begin(), pos.end()), pos.end());
  for(int x : pos) {
    tr[x] = 0;
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  for(cin >> t; t--; Solve()) {
  }
  return 0;
}

标签:le,limits,1801,int,Max,CF,max,id
From: https://www.cnblogs.com/yaosicheng124/p/18415815

相关文章

  • CF1039D You Are Given a Tree
    CF1039DYouAreGivenaTree咋其他题解都带根号?根号是坏文明,这里是俩\(\log\)做法,能够跑到\(300\)ms以内。首先考虑暴力贪心,从叶子向根合并,可以取出一条链的时候就取出来,否则就连一条尽可能长的链往上合并。具体的设\(f_{x,i}\)为当\(k=i\)时,在\(x\)处能取出的最......
  • CF1793E Velepin and Marketi
    首先发现,每个人过的题是不同的,所以我们不关心过了那些题目。我们要直接去求分成\(k\)组最多的通过数是不容易的。我们可以转换一下,求当\(i\)个题通过的时候__最多__分多少组。为什么记最多,因为化成\(k\)个组通过\(i\)题可以的情况下,我们可以任意合并两个组,保证依然可以......
  • [题解]CF542A Place Your Ad Here
    思路首先因为电视台比广告多一个信息,所以通常来说枚举电视台是更有前途的。因此枚举每一个电视台,考虑所有广告的贡献。对于一个电视台,\(c_i\)是定值,也就是找到所有广告与电视台所表示区间交得最多的那一个。假设枚举的电视台控制了\([L,R]\)区间,则广告\([l,r]\)会有三种方......
  • CF1187E sol
    首先不难发现,确定了根以后答案是固定的。设\(sz_i\)表示以1为根的树中,以1为根的子树大小;\(f_i\)表示以1为根的树中,以\(i\)为根的子树得到的最大权值,可以得到转移\[f_u=sz_u+\sum_{v\inson_u}f_v\]然后设\(g_v\)表示先选\(v\)的最大权值,\(v\)的父亲为\(......
  • CF605E
    题解总之,赞美太阳#include<bits/stdc++.h>usingnamespacestd;inlineintread(){ charc;intf=1,res=0; while(c=getchar(),!isdigit(c))if(c=='-')f*=-1; while(isdigit(c))res=res*10+c-'0',c=getchar(); returnres*f;}constintN=1e3+5......
  • 掌握CFML:在输出缓冲区中高效搜索字符串的技巧
    掌握CFML:在输出缓冲区中高效搜索字符串的技巧在开发过程中,特别是使用ColdFusionMarkupLanguage(CFML)进行Web开发时,处理大量数据并快速找到特定字符串是一项常见且重要的任务。为了提高程序效率,我们经常需要在输出缓冲区中搜索特定的字符串,并在必要时对其进行处理。本文将分......
  • 题解:CF1767E Algebra Flash
    可以在cnblogs中阅读。\(m\le40\)的数据范围提示让我们往颜色种类上考虑。由题每次可以跳\(1\)或\(2\)格,即存在一条从\(1\)到\(n\)的路径的充要条件是不存在两个相邻的未激活格。换句话说,对任意两个相邻的格子都必须选择至少一个激活。任意两个,至少一个,这样的条件......
  • 2024.9.12 CF1783 VP
    A:先将\(a\)降序排序,此时只有位置\(2\)有可能不满足条件。找到最小的\(i\ge2\)使得\(a_1\neqa_i\)(不存在则无解),然后交换\(a_2,a_i\),即为一个解。点击查看代码#include<bits/stdc++.h>#defineintlonglong#definepsbkpush_back#definefstfirst#definescdse......
  • Cf Round 953 (Div. 2) (A-D)
    https://codeforces.com/contest/1978C:D:#include<bits/stdc++.h>usingnamespacestd;#definepiipair<int,int>#definemkpmake_pair#definelowbit(x)((x&(-x)))#defineintlonglongconstintmaxn=2e5+10;constintmod=998244353;in......
  • Linux下sysfs_procfs_debugfs使用
    1Linux下sysfs/procfs/debugfs使用Linux内核空间与用户空间的交互如何能透过文件系统这层关系,把需要参数写入文件中呢?当然有办法,linux内核提供了3种“内存文件系统”,分别是sysfs、debugfs、procfs,驱动工程师可以通过任意的一种文件系统向用户空间传递信息。Sysfs的挂载点为/s......