zoukankan      html  css  js  c++  java
  • [bzoj1046][HAOI2007]上升序列

    一个有意思的题。
    很显然,这是LIS问题的加强版。
    对于每一个询问,我们从前到后检查每一个元素,如果f[i]>=x那么输出,然后x--。如果x最终为零,那么说明有解。
    证明:
    首先,由于我们是从前考虑的每一个元素,所以保证了字典序最小。
    其次,因为如果对于一个元素i|f[i]>x,那么从i后面一定至少能够找到x个元素使得构成一个长度为x的序列。
    考虑到字典序的定义,这样贪心一定是最优的。
    我们处理LIS时,令g[i]为使f[j]==i的最大j,这样可以用二分查照优化转移,复杂度从O(n2)降到了O(nlogn)
    当然,这个题目不优化,直接使用O(n2)的算法也完全可以卡过。
    下面上代码。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 10001;
    struct num {
        int value, pos;
        bool operator < (const num& b) const {
            return this->pos<b.pos;
        }
    } a[maxn];
    int n, m, Ma;
    int f[maxn];
    void getlis() {
        f[n-1] = 1;
        for(int i = n-2; i >= 0; i--) {
            int ans = 0;
            for(int j = i+1; j < n; j++) {
                if(a[j].value>a[i].value && f[j] > ans){ 
                    ans = f[j];
                }
            }
            f[i] = ans+1;
        }
    }
    void getlis2() {
        f[n-1] = 1;
        int g[maxn]; //define g[i] to be the max j that let f[j] = i
        memset(g, -1, sizeof(g));
        g[0] = 0x3f3f3f;
        for(int i = n - 1; i >= 0; i--) {
            int ans = 0;
            int L = 0;
            int R = n;
            while(L < R) {
                if(R-L <= 1) break;  //二分查找最小的比x大的元素
                int mid = (L+R)/2;
                if(g[mid] > a[i].value) L = mid;
                else R = mid;
            }
            ans = L;
            f[i] = ans+1;
            g[ans+1] = max(g[ans+1], a[i].value);
        }
    }
    void solve() {
        sort(a, a+n);
        scanf("%d", &m);
        while(m--) {
            int l;
            scanf("%d", &l);
            int x = l;
            int cnt = 0;
            int b[maxn];
            int lastpos = 0;
            for(int i = 0; i < n; i++) {
                if(f[a[i].pos] >= x && a[i].value> lastpos) {
                    b[cnt++] =  a[i].value;
                    x--;
                    lastpos = a[i].value;
                }
            }
            if(cnt < l-1) printf("%s
    ", "Impossible");
            else {
               for(int i = 0; i < l; i++) {
                  printf("%d", b[i]);
                  if(i!=l-1) putchar(' '); 
                 } 
               printf("
    ");
            }
        }
    }
    int main() {
        scanf("%d", &n);
        for(int i = 0; i < n; i++) {
            int x;
            scanf("%d", &x);
            a[i] = {x, i};
            Ma = max(Ma, x);
        }
        getlis2();
    //    for(int i = 0; i < n; i++) cout << f[i] << ' ';
    solve();
    }
    
  • 相关阅读:
    第五次实验报告
    第四次实验报告
    [_UICascadingTextStorage attributesAtIndex:effectiveRange:]: Range or index out of bounds
    真机测试时出现 could not find developer disk image问题
    UItableview正在滚动的时候进行操作容易出问题
    NSArray NSMutableArray 初始化
    日志报错Can't add self as subview
    设置statusBar状态栏颜色
    网站视频url地址获取
    ios9 xcode7以后编译需要进行的几项设置
  • 原文地址:https://www.cnblogs.com/gengchen/p/6323290.html
Copyright © 2011-2022 走看看