我是靠谱客的博主 优秀母鸡,最近开发中收集的这篇文章主要介绍12.CF558E A Simple Task 线段树维护字符串区间排序12.CF558E A Simple Task 线段树维护字符串区间排序,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

12.CF558E A Simple Task 线段树维护字符串区间排序

个人Limitの线段树题单题解主目录:Limitの线段树题单 题解目录_HeartFireY的博客-CSDN博客

要求对于给定的字符串,对给定的区间进行排序

线段树经典应用,维护26棵线段树,实现区间覆盖和查询即可。

洛谷传送门:CF558E A Simple Task - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

CF传送门:E. A Simple Task (codeforces.com)

题目分析

要求对于给定的字符串,对给定的区间进行排序。

我们维护 26 26 26棵线段树,每颗线段树上记录对应字母所在的位置(叶节点 0 − 1 0-1 01表示有没有,然后维护区间和表示区间字母个数)。对于区间排序,我们只需要取出区间在 26 26 26棵线段树上的信息,然后按照升序或降序覆盖即可。

因为要维护区间覆盖,因此也需要打 L a z y Lazy Lazy标记。

Code

#include <bits/stdc++.h>
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define int long long
#define endl 'n'
using namespace std;

const int N = 2e2 + 10, MOD = 1e9 + 7;

string s;

char ans[N];

namespace SegTree{
    #define ls rt << 1
    #define rs rt << 1 | 1
    #define lson ls, id, l, mid
    #define rson rs, id, mid + 1, r

    int tree[N << 2][26], lazy[N << 2][26];

    inline void push_up(int rt, int id){ tree[rt][id] = tree[ls][id] + tree[rs][id]; }

    inline void push_down(int rt, int id, int m){
        if(lazy[rt][id] == -1) return;
        lazy[ls][id] = lazy[rs][id] = lazy[rt][id];
        tree[ls][id] = lazy[rt][id] * (m - (m >> 1));
        tree[rs][id] = lazy[rt][id] * (m >> 1);
        lazy[rt][id] = -1;
    }
    void build(int rt, int id, int l, int r){
        lazy[rt][id] = -1, tree[rt][id] = 0;
        if(l == r){
            tree[rt][id] += (s[l] - 'a' == id);
            return;
        }
        int mid = l + r >> 1;
        build(lson), build(rson);
        push_up(rt, id);
    }

    void update(int rt, int id, int l, int r, int L, int R, int val){
        if(l >= L && r <= R){
            tree[rt][id] = val * (r - l + 1);
            lazy[rt][id] = val;
            return;
        }
        push_down(rt, id, r - l + 1);
        int mid = l + r >> 1;
        if(mid >= L) update(lson, L, R, val);
        if(mid < R) update(rson, L, R, val);
        push_up(rt, id);
    }

    int query(int rt, int id, int l, int r, int L, int R){
        if(l >= L && r <= R) return tree[rt][id];
        push_down(rt, id, r - l + 1);
        int mid = l + r >> 1, ans = 0;
        if(mid >= L) ans += query(lson, L, R);
        if(mid < R) ans += query(rson, L, R);
        return ans;
    }

    void getans(int rt, int id, int l, int r){
        if(l == r){
            if(tree[rt][id]) ans[l] = (char)('a' + id);
            return;
        }
        push_down(rt, id, r - l + 1);
        int mid = l + r >> 1;
        getans(lson), getans(rson);
    }
}


inline void solve(){
    int n, q; cin >> n >> q;
    cin >> s, s = '@' + s;
    for(int i = 0; i < 26; i++) SegTree::build(1, i, 1, n);
    while(q--){
        int l, r, k; cin >> l >> r >> k;
        vector<int> cnt;
        for(int i = 0; i < 26; i++) cnt.emplace_back(SegTree::query(1, i, 1, n, l, r));
        if(k){
            int curl = l, curr = l;
            for(int i = 0; i < 26; i++){
                if(!cnt[i]) continue;
                curr = curl + cnt[i] - 1;
                SegTree::update(1, i, 1, n, l, r, 0);
                SegTree::update(1, i, 1, n, curl, curr, 1);
                curl = curr + 1;
            }
            assert(curr == r);
        } else {
            int curl = l, curr = l;
            for(int i = 25; i >= 0; i--){
                if(!cnt[i]) continue;
                curr = curl + cnt[i] - 1;
                SegTree::update(1, i, 1, n, l, r, 0);
                SegTree::update(1, i, 1, n, curl, curr, 1);
                curl = curr + 1;
            }
            assert(curr == r);
        }
    }
    for(int i = 0; i < 26; i++) SegTree::getans(1, i, 1, n);
    for(int i = 1; i <= n; i++) cout << ans[i];
    cout << endl;
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    cout << fixed << setprecision(12);
    int t = 1; //cin >> t;
    while(t--) solve();
    return 0;
}

最后

以上就是优秀母鸡为你收集整理的12.CF558E A Simple Task 线段树维护字符串区间排序12.CF558E A Simple Task 线段树维护字符串区间排序的全部内容,希望文章能够帮你解决12.CF558E A Simple Task 线段树维护字符串区间排序12.CF558E A Simple Task 线段树维护字符串区间排序所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部