zoukankan      html  css  js  c++  java
  • bzoj1264

    dp+树状数组

    思维僵化怎么办。。。

    我们都知道,如果两个序列中所有元素都不相同,那么可以用lis求解,复杂度nlogn,但是这道题不行,每种元素出现了5次。。。然后我一直在想有没有什么解决办法

    事实上是这个样子的,考虑二维dp,dp[i][j]=dp[i-1][j-1]+1当且仅当s[i]==t[j],我们把这个看做一个点对(i,j),其实我们就是求一个最长的点对序列满足排序后一个点对在另一个点对左下方,那么这就是一个二维偏序,可以用排序lis解决,由于每种元素只出现5次,所以只有25*n对点对

     
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 5;
    struct data {
        int a, b;
        data() {}
        data(int a, int b) : a(a), b(b) {}
        bool friend operator < (const data &a, const data &b) {
            return a.a == b.a ? a.b > b.b : a.a < b.a;
        }
    } x[N * 5];
    vector<int> v1[N], v2[N];
    int n, cnt;
    int tree[N];
    void update(int x, int d) 
    {
        for(; x <= n; x += x & -x) tree[x] = max(tree[x], d);
    }
    int query(int x)
    {
        int ret = 0;
        for(; x; x -= x & -x) ret = max(ret, tree[x]);
        return ret;
    }
    int main()
    {
        scanf("%d", &n);
        n *= 5;
        for(int i = 1, x; i <= n; ++i) scanf("%d", &x), v1[x].push_back(i);
        for(int i = 1, x; i <= n; ++i) scanf("%d", &x), v2[x].push_back(i);
        for(int i = 1; i <= n / 5; ++i)
            for(int j = 0; j < v1[i].size(); ++j)
                for(int k = 0; k < v2[i].size(); ++k) 
                    x[++cnt] = data(v1[i][j], v2[i][k]);
        sort(x + 1, x + cnt + 1);           
        for(int i = 1; i <= cnt; ++i)
        {
            int tmp = query(x[i].b - 1) + 1;
            update(x[i].b, tmp);
        }
        printf("%d
    ", query(n));
        return 0;
    }
    View Code
  • 相关阅读:
    【转】NSArray,NSSet,NSDictionary总结
    dequeueReusableCellWithIdentifier
    可任意自定义的UITableViewCell
    contentSize、contentInset和contentOffset区别
    Cocoa的MVC架构分析 delegate
    WP7 Toolkit ExpanderView 控件 介绍 02
    ObjectiveC中一种消息处理方法performSelector: withObject:
    [转]HTML5多点触摸演示源码(Canvas绘制演示)
    Matlab 积分图的快速计算
    测试
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7774683.html
Copyright © 2011-2022 走看看