• 【洛谷4215】踩气球(线段树)


    题目:

    洛谷4215

    分析:

    感觉思路有点像线段树分治?

    把所有区间插到线段树上。我一开始的想法是修改时给树上一条链上包含的所有熊孩子的值都减(1),然后发现这个单次最坏是(O(m))的,gg

    可以记录每个熊孩子被分成了多少个非零的区间。修改时如果某个区间变成(0)了,那么就给包含该区间的熊孩子的区间数减(1),这样均摊最多有(mlog m)个区间,总复杂度(O(qlog n+mlog n))。和暴力相比,这样做相当于把每个熊孩子最多分的段数从(n)(每个位置一段)变成了(log n)

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cctype>
    using namespace std;
    #define _ 0
    
    namespace zyt
    {
        template<typename T>
        inline void read(T &x)
        {
            char c;
            bool f = false;
            x = 0;
            do
                c = getchar();
            while (c != '-' && !isdigit(c));
            if (c == '-')
                f = true, c = getchar();
            do
                x = x * 10 + c - '0', c = getchar();
            while (isdigit(c));
            if (f)
                x = -x;
        }
        template<typename T>
        inline void write(T x)
        {
            static char buf[20];
            char *pos = buf;
            if (x < 0)
                putchar('-'), x = -x;
            do
                *pos++ = x % 10 + '0';
            while (x /= 10);
            while (pos > buf)
                putchar(*--pos);
        }
        const int N = 1e5 + 10, B = 17;
        struct edge
        {
            int to, next;
        }e[N * B];
        int n, m, q, arr[N], seg[N], head[1 << (B + 1) | 11], ecnt, ans;
        inline void add(const int a, const int b)
        {
            e[ecnt] = (edge){b, head[a]}, head[a] = ecnt++;
        }
        namespace Segment_Tree
        {
            struct node
            {
                int sum;
            }tree[1 << (B + 1) | 11];
            inline void update(const int rot)
            {
                tree[rot].sum = tree[rot << 1].sum + tree[rot << 1 | 1].sum;
            }
            void build(const int rot, const int lt, const int rt)
            {
                head[rot] = -1;
                if (lt == rt)
                {
                    tree[rot].sum = arr[lt];
                    return;
                }
                int mid = (lt + rt) >> 1;
                build(rot << 1, lt, mid);
                build(rot << 1 | 1, mid + 1, rt);
                update(rot);
            }
            void insert(const int rot, const int lt, const int rt, const int ls, const int rs, const int id)
            {
                if (ls <= lt && rt <= rs)
                {
                    if (tree[rot].sum)
                        ++seg[id];
                    add(rot, id);
                    return;
                }
                int mid = (lt + rt) >> 1;
                if (ls <= mid)
                    insert(rot << 1, lt, mid, ls, rs, id);
                if (rs > mid)
                    insert(rot << 1 | 1, mid + 1, rt, ls, rs, id);
            }
            void change(const int rot, const int lt, const int rt, const int pos)
            {
                if (lt == rt)
                    --tree[rot].sum;
                else
                {
                    int mid = (lt + rt) >> 1;
                    if (pos <= mid)
                        change(rot << 1, lt, mid, pos);
                    else
                        change(rot << 1 | 1, mid + 1, rt, pos);
                    update(rot);
                }
                if (!tree[rot].sum)
                    for (int i = head[rot]; ~i; i = e[i].next)
                        if (!--seg[e[i].to])
                            ++ans;
            }
        }
        int work()
        {
            using namespace Segment_Tree;
            read(n), read(m);
            for (int i = 1; i <= n; i++)
                read(arr[i]);
            build(1, 1, n);
            for (int i = 1; i <= m; i++)
            {
                int l, r;
                read(l), read(r);
                insert(1, 1, n, l, r, i);
                if (!seg[i])
                    ++ans;
            }
            read(q);
            int lastans = 0;
            while (q--)
            {
                int x;
                read(x);
                x = (x + lastans - 1) % n + 1;
                change(1, 1, n, x);
                write(lastans = ans), putchar('
    ');
            }
            return ~~(0^_^0);
        }
    }
    int main()
    {
        return zyt::work();
    }
    
  • 相关阅读:
    springboot启动加载自定义插件
    sql记录
    集成WebMvcConfigurationSupport后,swagger3.0页面404无法访问 heamin
    [HTML/CSS] 超炫Loading动画
    [HTML/CSS] 简单的Menu图标
    Mysql笔记
    性能指标
    Select IO多路复用。
    Java垃圾回收
    JAVAAQS(AbstractQueuedSynchronizer)
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/10117429.html
Copyright © 2020-2023  润新知