[CF1801C] Music Festival
先只保留每个专辑中有用的数,这样每个专辑是一个单调递增的序列。因为只用考虑数的相对大小,所以对剩下的数进行离散化。设 \(f_i\) 为若序列从大于等于 \(i\) 的数开始,能够得到的最大印象值。从后往前 dp ,显然\(f_{i+1}\) 可转移到 \(f_i\) ,同时我们可以找到各个专辑中值为 \(i\) 的数,从这个数开始听。设该专辑中最后的数为 \(x\) ,且与 \(i\) 之间的数共有 \(num\) 个(包括 \(i\) 和 \(x\)),则 \(f_{x+1} + num\) 可转移至 \(f_i\) 。\(f_1\) 即为答案。
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=2e5+3;
struct hh{
int id,pos;
};
vector<int>a[N];
vector<hh>b[N];
int n,f[N],c[N];
IL int in()
{
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
void solve(){
n=in();c[0]=0;
for(int i=1;i<=n;++i){
int x,Max=0,len=in();
for(int j=1;j<=len;++j){
x=in();
if(x>Max){
Max=x,a[i].push_back(x);
b[x].push_back((hh){i,(int)(a[i].size()-1)}),c[++c[0]]=x;
}
}
}
sort(c+1,c+c[0]+1),c[0]=unique(c+1,c+c[0]+1)-c-1;
f[c[0]]=1;f[c[0]+1]=0;
for(int i=c[0]-1;i;--i){
f[i]=f[i+1];
for(auto v:b[c[i]]){
f[i]=max(f[i],(int)(a[v.id].size()-v.pos+f[lower_bound(c+1,c+c[0]+1,*a[v.id].rbegin())-c+1]));
}
}
for(int i=1;i<=n;++i){
for(auto v:a[i])
b[v].clear();
a[i].clear();
}
printf("%d\n",f[1]);
}
int main()
{
int T=in();
while(T--) solve();
return 0;
}