zoukankan      html  css  js  c++  java
  • 模板汇总 —— 杨式图表

    HDU - 6642

    使用范围:

    求k个不相交的子序列最大值之和。

    用法:

    开k个map, 每次对于新的一个v,我们插入 v 个 v 到第一层中。

    插入方式:

    1.如果没有数比这个v大, 我们就直接将v放入到该层。

    2.否则大于v的最小的数x,用v来替换x,将x插入下一层。

    因为不能一个一个插入,所以用map来一起插入。

    最后答案就是所有表内的元素个数之和。

    复杂度为(2^knlog(n))

    原理(口胡版):

    首先考虑,用数组直接求LIS问题,我们数组的最后其实并不一定是一个LIS,我们只是求出了一个最易于后续扩张的数组。

    对于杨表来讲,其实也一样,我们其实并没有保证了他的一个表内的数组完全是合法的,我们也一样找到了一个最易于后续扩张的一个数组。

    对于贡献来讲, 我们一开始其实在插入数的时候,就已经把贡献给算完了,只有这个数的所有数都被其他数删除的时候,他对答案才不会有影响。

    考虑 1 7 5 5 这个序列,且只有一层的杨表。

    我们插入1 7之后,  表内为  1 7777777.

    然后我们插入一个5, 表内为 1 5555577.

    我们可以发现在这个过程中,还是由7对答案产生的一个影响。

    我们再插入一个5,表内为 1 5555555 555.

    我们就发现答案会加上3。

    总结的话,也就是说,我们一旦成功(插入方式1)的插入某个数,我门就会对答案产生影响, 但是如果我们使用替换(插入方式2)来插入某个数的话,其实他的影响还是被原来的那个数给控制的。

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 2e5 +100;
    map<int, LL> mp[5];
    const int k = 5;
    LL ans = 0;
    void Insert(int v, int num, int id){
        if(id == k){
            return ;
        }
        map<int, LL>::iterator it;
        while(num){
            it = mp[id].upper_bound(v);
            if(it == mp[id].end()) {
                ans += num;
                mp[id][v] += num;
                num = 0;
            }
            else {
                int mn = min((LL)num, it->se);
                it->se -= mn;
                if(it->se == 0) mp[id].erase(it);
                Insert(it->fi, mn, id+1);
                mp[id][v] += mn;
                num -= mn;
            }
        }
    }
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            int n;
            for(int i = 0; i < 5; ++i) mp[i].clear();
            scanf("%d", &n);
            ans = 0;
            for(int i = 1, v; i <= n; ++i){
                scanf("%d", &v);
                Insert(v, v, 0);
                printf("%lld%c", ans, " 
    "[i==n]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HTML框架
    HTML链接
    kzalloc 函数详解(转载)
    LCD接口(转载)
    S3C2440上RTC时钟驱动开发实例讲解(转载)
    PHP 真值与空值
    http chunked 理解
    c# 基础
    美式音标注意事项
    groovy 闭包
  • 原文地址:https://www.cnblogs.com/MingSD/p/11346605.html
Copyright © 2011-2022 走看看