CFGYM101915 I A Movie in Byteland (二维LIS+树状数组优化dp)

Mean

给定\(n\)个演员的姓名,问最多能按原顺序选出多少名演员,满足以下条件。
1.连续的两个演员中,一个演员的名字中带\(m\)字母,另一个演员的名字中不带\(m\)字母.
2.对于演员每个\(i\),对于演员\(j<i\),要保证\(s_i>=s_j \and reverse(s_i)>=reverse(s_j)\)

Sol

二维\(LIS\)+树状数组优化

\(s_i\)为第一维,\(reverse(s_i)\)为第二维.

先按第一维的字典序从小到大排序,然后将第二维的字符串离散化.

则有了暴力的\(dp\)转移
\(dp[i][j]\)表示在前\(i\)个字符串中选取,且选取了第\(i\)个字符串有\(m\)或无\(m\)的最多合法人数.

如果当前字符串\(i\)不含有\(m\),\(dp[i][0]=\max_{j=0}^{i-1}(dp[j][1])+1\)
否则 \(dp[i][1]=\max_{j=0}^{i-1}(dp[j][0])+1\)

注意到取\(max\)的过程是前缀最大值关系,所以可以维护两个树状数组优化一下即可.

\(O(nlogn)\).

Code

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
#define lowbit(x) (x&(-x))
#define debug(x) cout<<#x<<" :"<<x<<endl
#define debug1(x) cout<<#x<<" :"<<x<<" "
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+20;
const int M=1e5+10;
const int MAX=10000007;
inline int read() {
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
    return x*f;
}

inline void out(int x) {   
    if(x>9) out(x/10);   
    putchar(x%10+'0'); 
}     
/*
二维LIS 树状数组优化
 */
int t,n;
char s[N];
int vis[N];
string a[N],b[N],c[N];
int c1[N],c0[N];
int rk[N];
void add(int q[],int pos,int val){
    while(pos<N){
        q[pos]=max(q[pos],val);
        pos+=lowbit(pos);
    }
}
int get(int q[],int pos){
    int ans=0;
    while(pos){
        ans=max(ans,q[pos]);
        pos-=lowbit(pos);
    }
    return ans;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        rep(i,1,n+10)c1[i]=c0[i]=0;
        rep(i,1,n)a[i].clear();
        rep(i,1,n){
            scanf("%s",s);
            a[i]=s;
        }
        sort(a+1,a+1+n);
        rep(i,1,n){
            vis[i]=0;
            rep(j,0,(int)a[i].size()-1){
                vis[i]|=(a[i][j]=='m');
            }
        }
        rep(i,1,n){
            b[i]=a[i];
            reverse(b[i].begin(),b[i].end());
            c[i]=b[i];
        }
        sort(c+1,c+1+n);
        int sz=unique(c+1,c+1+n)-(c+1);
        rep(i,1,n){
            rk[i]=lower_bound(c+1,c+1+sz,b[i])-c+1;
        }
        int mx=0;
        rep(i,1,n){
            if(vis[i]){
                int p=get(c0,rk[i]);
                mx=max(mx,p+1);
                add(c1,rk[i],p+1);
            }
            else{
                int p=get(c1,rk[i]);
                mx=max(mx,p+1);
                add(c0,rk[i],p+1);
            }
        }
        printf("%d\n",mx);
    }
    return 0;
}
posted @ 2021-10-18 16:52  Qquun  阅读(76)  评论(0)    收藏  举报