• 【AHOI2006】基因匹配


    题面

    题解

    众所周知,最长公共子序列的$dp$是$ ext{O}(n^2)$,

    但是每一个数字只重复$5$遍,那么我们暴力匹配$25n$个点对

    那么我们就可以将其变成求最长上升子序列

    用二分栈或者树状数组求解即可。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<vector>
    #define RG register
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while(ch != '-' && (!isdigit(ch))) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(20010), maxm(500010);
    int n, m, a[maxm], c[maxm], f[maxm], cnt, ans;
    std::vector<int> G[maxn];
    
    void add(int x, int v) { while(x <= m) c[x] = std::max(c[x], v), x += x & -x; }
    int query(int x)
    {
    	int ans = 0;
    	while(x) ans = std::max(ans, c[x]), x -= x & -x;
    	return ans;
    }
    
    int main()
    {
    	m = (n = read()) * 5;
    	for(RG int i = 1; i <= m; i++)
    		G[read()].push_back(i);
    	for(RG int i = 1, x; i <= m; i++)
    	{
    		x = read();
    		for(RG int j = 4; ~j; j--) a[++cnt] = G[x][j];
    	}
    	for(RG int i = 1; i <= cnt; i++)
    		f[i] = query(a[i] - 1) + 1, add(a[i], f[i]),
    		ans = std::max(ans, f[i]);
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    HDU 5438 Ponds
    [HNOI2013]比赛
    [HNOI2009]最小圈
    【模板】高斯消元法
    控制公司 Controlling Companies
    sdut 2878 圆圈
    滑雪
    [ZJOI2010]排列计数
    [HNOI2003]激光炸弹
    [BZOJ 3732]Network
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10246929.html
Copyright © 2020-2023  润新知