• [CF558E] A Simple Task


    [CF558E] A Simple Task - 线段树

    Description

    给定一个长度不超过 (10^5) 的字符串(小写英文字母),和不超过 50000 个操作。每个操作 L R K 表示给区间 [L,R] 的字符串排序,K=1 为升序,K=0 为降序。

    Solution

    线段树,每个结点维护区间内 26 个字母的出现次数,对每次排序操作暴力重新覆盖。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    struct SegmentTree
    {
        int n;
    
        struct Node
        {
            array<int, 27> a;
            int tag=0;
            void put(int x, int len)
            {
                tag = x + 1;
                for (int i = 0; i < 26; i++)
                    a[i] = 0;
                a[x] = len;
            }
            Node operator+(const Node &rhs) const
            {
                auto res = *this;
                for (int i = 0; i < 26; i++)
                    res.a[i] += rhs.a[i];
                res.tag=0;
                return res;
            }
        };
    
        vector<Node> nodes;
    
        SegmentTree(int n) : n(n)
        {
            nodes.resize(4 * n + 8);
        }
    
        void pushup(int p)
        {
            nodes[p] = nodes[p * 2] + nodes[p * 2 + 1];
        }
    
        void pushdown(int p, int l, int r)
        {
            if (nodes[p].tag)
            {
                nodes[p * 2].put(nodes[p].tag - 1, (l + r) / 2 - l + 1);
                nodes[p * 2 + 1].put(nodes[p].tag - 1, r - (l + r) / 2);
                nodes[p].tag = 0;
            }
        }
    
        void build(int p, int l, int r, const string &str)
        {
            if (l == r)
                nodes[p].put(str[l - 1] - 'a', 1);
            else
            {
                build(p * 2, l, (l + r) / 2, str);
                build(p * 2 + 1, (l + r) / 2 + 1, r, str);
                pushup(p);
            }
        }
    
        void Build(const string &str)
        {
            build(1, 1, n, str);
        }
    
        void modify(int p, int l, int r, int ql, int qr, int x)
        {
            if (l > qr || r < ql)
                return;
            if (l >= ql && r <= qr)
                nodes[p].put(x, r - l + 1);
            else
            {
                pushdown(p, l, r);
                modify(p * 2, l, (l + r) / 2, ql, qr, x);
                modify(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr, x);
                pushup(p);
            }
        }
    
        void Modify(int ql, int qr, int x)
        {
            if (ql > qr)
                return;
            // cout << "Modify " << ql << ", " << qr << ", " << x << endl;
            modify(1, 1, n, ql, qr, x);
        }
    
        Node query(int p, int l, int r, int ql, int qr)
        {
            if (l > qr || r < ql)
                return Node();
            if (l >= ql && r <= qr)
                return nodes[p];
            pushdown(p, l, r);
            return query(p * 2, l, (l + r) / 2, ql, qr) + query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
        }
    
        Node Query(int ql, int qr)
        {
            return query(1, 1, n, ql, qr);
        }
    
        void SortAsc(int ql, int qr)
        {
            Node res = Query(ql, qr);
            int l = ql;
            for (int i = 0; i < 26; i++)
            {
                int r = l + res.a[i] - 1;
                Modify(l, r, i);
                l = r + 1;
            }
            assert(l == qr + 1);
        }
    
        void SortDesc(int ql, int qr)
        {
            Node res = Query(ql, qr);
            int l = ql;
            for (int i = 25; i >= 0; i--)
            {
                int r = l + res.a[i] - 1;
                Modify(l, r, i);
                l = r + 1;
            }
            assert(l == qr + 1);
        }
    
        void print(int p, int l, int r)
        {
            if (l == r)
            {
                for (int i = 0; i < 26; i++)
                    if (nodes[p].a[i])
                    {
                        cout << (char)(i + 'a');
                    }
            }
            else
            {
                pushdown(p, l, r);
                print(p * 2, l, (l + r) / 2);
                print(p * 2 + 1, (l + r) / 2 + 1, r);
            }
        }
    
        void Print()
        {
            print(1, 1, n);
        }
    };
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        int n, m;
        string s;
        cin >> n >> m >> s;
    
        SegmentTree seg(n);
        seg.Build(s);
    
        for (int i = 1; i <= m; i++)
        {
            int l, r, k;
            cin >> l >> r >> k;
    
            if (k == 1)
            {
                seg.SortAsc(l, r);
            }
            else
            {
                seg.SortDesc(l, r);
            }
    
            // seg.Print();
        }
    
        seg.Print();
    }
    
  • 相关阅读:
    Jenkins安装2
    11月14 vagrant 虚拟机连接
    11月13 ssh 和 netstat
    Jenkins安装
    11月12号 springboot1.5 引入redis
    11月12号 用户登录输入密码错误达到指定次数后,锁定账户 004
    js模式-观察者模式
    立即执行函数
    vue 获取数据
    在登陆退出时候使用Vuex
  • 原文地址:https://www.cnblogs.com/mollnn/p/14350569.html
Copyright © 2020-2023  润新知