回头看了看LCS。做了几道水题,被一道题的时间给卡住了
题目:UVA10635
用常规的LCS做法做,怎么都超时间,想了想,一共62500那么大,n^2的时间复杂度确实是太高了,看了下白书,发现用LIS的方式很简单就能做出来,而且因为每个数字不一样,时间复杂度降低到了nlogn的复杂的。
思路大概就是因为要用LIS,所以需要有序,我们思考一下怎么才能有序呢,输入的顺序就是有序的,那么我们把输入顺序作为一个数组来考虑。
第二行输入的时候,就可以查询上一个,以输入顺序作为值的数组,查看是否有值,有的话表明能够对上,所以再进行LIS的操作就行了。
算法主要是因为,变得有序了,所以能够二分查看答案,这样就降低了复杂度。
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const long long INF = 0x3f3f3f3f;
using namespace std;
int t;
int n, p, q;
int vis[1000005];
int sc[1000005];
int dp[1000005];
int main()
{
cin >> t;
up(i, 0, t)
{
cin >> n >> p >> q;
memset(vis, -1, sizeof(vis));
memset(dp, -1, sizeof(dp));
upd(j, 0, p)
{
scanf("%d", &sc[j]);
vis[sc[j]] = j;
}
upd(j, 0, q)
{
scanf("%d", &sc[j]);
sc[j] = vis[sc[j]];
}
int top = 1;
upd(j, 0, q)
{
if (sc[j] == -1) continue;
if (sc[j] > dp[top-1])
{
dp[top++] = sc[j];
//cout << "top" << top<<"dp"<<dp[top-1] << endl;
}
else
{
int lf = 0, rt = top;
while (lf <= rt)
{
int mid = (lf + rt) >> 1;
if (sc[j] > dp[mid])
{
lf = mid + 1;
continue;
}
else
{
rt = mid - 1;
continue;
}
}
dp[lf] = sc[j];
}
}
printf("Case %d: ", i + 1);
cout << top-1 << endl;
}
return 0;
}