[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;
    
}

posted @ 2023-03-09 21:50  (o-ωq)).oO  阅读(56)  评论(0编辑  收藏  举报