zoukankan      html  css  js  c++  java
  • HDU

    cdq分治+树状数组

    很久没写cdq分治了,大概有两年了?

    求答案最小字典序有个小trick,倒着求一个f[i]表示以i开始最长的序列长度,最后输出的时候从前往后扫f,第一个等于答案且满足前面已经选定的点带来的限制的点就可以添加到答案序列里来。

    cdq分治求解中先处理后半部分,再计算后半部分的贡献,再计算前半部分。注意,计算贡献需要按某一维排序,然后类似归并地处理,用bit来取max,但递归前半部分时需要恢复序列按id的增序。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 5e4 + 100;
    
    struct Point {
        int x, y;
        int id;
    } p[MAXN];
    int f[MAXN];
    
    bool cmp(const Point&a, const Point&b) {
        return a.id < b.id;
    }
    bool cmp2(const Point&a, const Point&b) {
        return a.x < b.x || (a.x == b.x && (a.y > b.y || (a.y == b.y && a.id < b.id)));
    }
    
    int b[MAXN * 2];
    void upd(int p, int v) {
        //b[p] = v;
        //return ;
        for (; p < MAXN * 2; b[p] = max(b[p], v), p += p&-p);
    }
    void clr(int p) {
        //b[p] = 0;
        //return ;
        for (; p < MAXN * 2; b[p] = 0, p += p&-p);
    }
    int qry(int p) {
        int r = 0;
        //for (int i = 1; i <= p; ++i)
        //    r = max(r, b[i]);
        //return r;
        for (; 0 < p; r = max(r, b[p]), p -= p&-p);
        return r;
    }
    
    void cdq(int l, int r) {
        if (l == r) return ;
        int m = (l + r) >> 1;
        cdq(m + 1, r);
        sort(p + m + 1, p + r + 1, cmp2);
        sort(p + l, p + m + 1, cmp2);
        for (int i = m, j = r; l <= i; --i) {
            while (m < j && p[i].x <= p[j].x) upd(p[j].y, f[p[j].id]), --j;
            f[p[i].id] = max(f[p[i].id], 1 + qry(p[i].y));
        }
        for (int j = r; m < j; --j)
            clr(p[j].y);
        sort(p + l, p + m + 1, cmp);
        cdq(l, m);
    }
    
    int main() {
    #ifdef lol
        freopen("code.in", "r", stdin);
        freopen("code.out", "w", stdout);
    #endif
    
        int n;
        while (scanf("%d", &n) != EOF) {
            int c = 0, *t = new int[n * 2];
            for (int i = 1; i <= n; ++i)
                scanf("%d", &p[i].y), t[c++] = p[i].y;
            for (int i = 1; i <= n; ++i)
                scanf("%d", &p[i].x), t[c++] = p[i].x;
            sort(t, t + c);
            for (int i = 1; i <= n; ++i) {
                p[i].x = lower_bound(t, t + c, p[i].x) - t + 1;
                p[i].y = lower_bound(t, t + c, p[i].y) - t + 1;
                p[i].id = i;
                f[i] = 1;
            }
            delete t;
            cdq(1, n);
            sort(p + 1, p + n + 1, cmp);
            int ans = 0;
            for (int i = 1; i <= n; ++i) {
                ans = max(ans, f[i]);
            }
            printf("%d
    ", ans);
            for (int i = 1, j = 0; i <= n; ++i)
                if (f[i] == ans && (j == 0 || (p[j].x <= p[i].x && p[i].y <= p[j].y))) {
                    printf("%d%c", i, " 
    "[(--ans) == 0]);
                    j = i;
                }
        }
        return 0;
    }
  • 相关阅读:
    mac上eclipse上运行word count
    利用hadoop自带程序运行wordcount
    mac上eclipse上配置hadoop
    在mac上安装hadoop伪分布式
    0到N数其中三个数的全排列
    【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查
    【设计模式】【行为型模式】策略模式
    【设计模式】【行为型模式】模板模式
    properties文件操作
    File相关操作
  • 原文地址:https://www.cnblogs.com/ichn/p/7106050.html
Copyright © 2011-2022 走看看