如果直接使用LCS
来解决,那么复杂度为 \(O(pq)\) ,显然会超时。
因为给出的两个序列的数都是互不相同的,我们将第一个序列的数按 \(1,2,3...\) 依次编号,然后将第二个序列的数(当然这个数应该是存在于第一个序列的)按照数值映射到相应的编号中,注意到题目所求的LCS
恰好就是第二个数列对应的编号的最长上升子序列(LIS
)长度。
#pragma GCC optimize("O3") #include<bits/stdc++.h> using namespace std; #define endl '\n' #define debug(x) cerr << #x << ": " << x << endl #define pb(a) push_back(a) #define set0(a) memset(a,0,sizeof(a)) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define dwn(i,a,b) for(int i=(a);i>=(b);i--) #define ceil(a,b) (a+(b-1))/b #define INF 0x3f3f3f3f #define ll_INF 0x7f7f7f7f7f7f7f7f typedef long long ll; typedef pair<int,int> PII; typedef pair<double,double> PDD; inline void read(int &x) { int s=0;x=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')x=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar(); x*=s; } const int N=1e5+5; int a[N]; int stk[N], top; int tr[N]; int lowbit(int x){return x&-x;} int query(int p){ int res=-1; for(; p; p-=lowbit(p)) res=max(res, tr[p]); return res; } void modify(int p, int v){ for(; p<N; p+=lowbit(p)) tr[p]=max(tr[p], v); } int main(){ int T; cin>>T; int cases=0; while(T--){ int n, p, q; read(n), read(p), read(q); int t; read(t); int tot=0; map<int, int> mp; rep(i,1,p) read(a[i]), mp[a[i]]=++tot; read(t); top=0; rep(i,1,q){ int k; read(k); if(!mp.count(k)) continue; stk[++top]=mp[k]; } // solve the longest increase sequence set0(tr); int res=0; rep(i,1,top){ int t=query(stk[i])+1; res=max(res, t); modify(stk[i]+1, t); } res++; printf("Case %d: %d\n", ++cases, res); } return 0; }