• 题解 P3527 【[POI2011]MET-Meteors】


    (Large exttt{P3527})

    题意

    一个环形被分为 (m) 份,每份都属于 (n) 个国家之一,有 (k) 场陨石,每场对应环上一段区间,为此区间上每份的隶属国家增加 (a_i) 的贡献,每个国家期望得到 (p_i) 的陨石,问第几波陨石过后能够达成目标?

    (n,m,kle 3e5)

    思路

    因为答案具有可二分性,即可以二分在第几波陨石达成目标,因为有修改,一个一个国家二分显得有点浪费,可以联想到整体二分,二分所有国家的完成时间,而修改操作可以由树状数组(区间修改,单点查询)来实现,注意要在最后加一波无限大的陨石特判 ( exttt{NIE}) 的情况。

    对于查询,直接用树状数组暴力一个一个查询当前块内所有国家的所有环形上的区域。

    时间复杂度为 (O(Nlog^2N))

    以下给出时间复杂度的证明。

    证明

    主要时间复杂度产生在修改和查询两种操作上。

    注意 (n,m,k) 同阶。

    对于修改:第 (i) 场陨石在整理二分中是从 ([1,k+1]) 这个区间到 ([i,i]) 这个区间,一共约有 (log_2 k) 层,每层都对其执行两遍(一遍修改,一遍清除)修改操作,修改操作复杂度约为 (O(log_2 m)) ,所以总复杂度约为 (O(Nlog^2N))

    对于查询:看起来是暴力一个一个查询,但是对于环形上每个区域,也都是在 (log_2 k) 层上每层都都做一次 (O(log_2 m)) 的查询,所以复杂度也是 (O(Nlog^2N))

    代码

    int a, b, c, p[N + 10], s[N + 10], ans[N + 10];
    vector<int> st[N + 10], Q, L, R;
    struct node
    {
        int opt, id, x, y, z;
    } ask[N + 10];
    
    inline void add(int n, int k)
    {
        if (!n)
            return;
        for (; n <= b; n += n & -n)
            p[n] += k;
    }
    
    inline int query(int n)
    {
        int res = 0;
        for (; n; n -= n & -n)
            res += p[n];
        return res;
    }
    
    inline void change(int l, int r, int val)
    {
        if (l <= r)
            add(l, val), add(r + 1, -val);
        else
            add(1, val), add(r + 1, -val), add(l, val);
    }
    
    inline void solve(int l, int r)
    {
        if (l == r)
        {
            for (int i = 0; i < Q.size(); i++)
                if (ask[Q[i]].opt == 2)
                    ans[ask[Q[i]].id] = l;
            return;
        }
        int mid = (l + r) >> 1;
        for (int i = 0; i < Q.size(); i++)
        {
            int n = Q[i];
            if (ask[n].opt == 1)
            {
                if (ask[n].id <= mid)
                    change(ask[n].x, ask[n].y, ask[n].z), L.PB(n);
                else
                    R.PB(n);
            }
            else
            {
                int tmp = 0;
                for (int j = 0; j < st[ask[n].id].size(); j++)
                {
                    int m = st[ask[n].id][j];
                    tmp += query(m);
                    if (tmp >= s[ask[n].id])
                        break;
                }
                if (s[ask[n].id] <= tmp)
                    L.PB(n);
                else
                    R.PB(n), s[ask[n].id] -= tmp;
            }
        }
        for (int i = 0; i < L.size(); i++)
        {
            int n = L[i];
            if (ask[n].opt != 1)
                continue;
            change(ask[n].x, ask[n].y, -ask[n].z);
        }
        vector<int> tmp = R;
        Q = L;
        R.clear();
        L.clear();
        solve(l, mid);
        Q = tmp;
        solve(mid + 1, r);
    }
    
    signed main()
    {
        // freopen("in1.in", "r", stdin);
        a = read();
        b = read();
        for (int i = 1; i <= b; i++)
            st[read()].PB(i);
        for (int i = 1; i <= a; i++)
            s[i] = read();
        c = read();
        for (int i = 1; i <= c; i++)
        {
            ask[i].opt = 1;
            ask[i].id = i;
            ask[i].x = read();
            ask[i].y = read();
            ask[i].z = read();
        }
        ask[++c].opt = 1;
        ask[c].id = c;
        ask[c].x = 1;
        ask[c].y = b;
        ask[c].z = 1e9;
        for (int i = 1; i <= a; i++)
            ask[i + c].opt = 2, ask[i + c].id = i;
        c += a;
        for (int i = 1; i <= c; i++)
            Q.PB(i);
        solve(1, c - a);
        for (int i = 1; i <= a; i++)
            if (ans[i] != c - a)
                printf("%d
    ", ans[i]);
            else
                puts("NIE");
        return 0;
    }
    
  • 相关阅读:
    scroll 滚动到指定位置触发事件 and 点击一按钮/链接让页面定位在指定的位置
    带三角形下标的提示框(按钮button)
    点击按钮,弹出遮罩层,跳转页面播放视频
    转换时间方法
    $(window).scrollTop() == $(document).height()
    html(),val(),text()的区别
    5秒后,页面跳转
    jquery 日期和时间的逻辑,比较大小
    JS JSON格式操作
    Bootstrap教程 之 网格系统和排版
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/14403375.html
Copyright © 2020-2023  润新知