zoukankan      html  css  js  c++  java
  • 「JOISC2016」俄罗斯套娃

    传送门

    我们可以把这些套娃抽象成平面直角坐标系里的点(不妨设 R 为横坐标,H 为纵坐标)。

    然后我们离线,把每个询问也抽象成这样的点。

    然后我们从右下至左上依次加点。

    那么我们每次的询问就是询问该点右下区域内的答案。

    考虑怎么计算:类似网络流最小割的,我们不难发现,一个区域内点的答案就是这些点可以构成的最长的一条链,满足这条链的形态是从左上到右下的。

    可以自己画图理解一下。

    然后拿一个树状数组就可以轻松维护了。

    参考代码:

    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    const int _ = 4e5 + 5;
    
    int n, q, x, y, X[_], c[_], ans[_];
    struct node { int x, y, id; } t[_];
    
    void update(int x, int v) { while (x < _) c[x] = max(c[x], v), x += x & -x; }
    int query(int x) { int res = 0; while (x) res = max(res, c[x]), x -= x & -x; return res; }
    
    int cmp(node a, node b) { 
        if (a.x != b.x) return a.x > b.x;
        if (a.y != b.y) return a.y < b.y;
        return a.id < b.id;
    }
    
    int main() {
        scanf("%d %d", &n, &q);
        for (int i = 1; i <= n + q; ++i)
            scanf("%d %d", &x, &y), X[++X[0]] = y, t[i] = (node) { x, y, i > n ? i - n : 0 };
        sort(t + 1, t + n + q + 1, cmp);
        sort(X + 1, X + X[0] + 1);
        X[0] = unique(X + 1, X + X[0] + 1) - X - 1;
        for (int i = 1; i <= n + q; ++i)
            t[i].y = lower_bound(X + 1, X + X[0] + 1, t[i].y) - X;
        for (int i = 1; i <= n + q; ++i) {
            if (t[i].id) 
                ans[t[i].id] = query(t[i].y);
            else
                x = query(t[i].y), update(t[i].y, x + 1);
        }
        for (int i = 1; i <= q; ++i) printf("%d
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    电路原理图分析
    GPIO学习——用户空间操作
    在Android上运行Java和C程序
    Android命令行工具学习总结
    Android蓝牙学习笔记
    33 把数组排成最小的数
    233 Number of Digit One
    32 从1到n整数中1出现的次数
    31 连续子数组的最大和
    《大型网站技术架构》学习笔记
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12900816.html
Copyright © 2011-2022 走看看