• E. A Simple Task


    E. A Simple Task

    这个题目的意思是 给你一个由小写字母组成的字符串,有两种操作

    i j k 如果k==1 那么就是就把i 到 j 的这个区间非递减排序。

    i j k如果k==2 那么就是把 i 到 j 这个区间非递增排序。

    n 有 1e5  q(操作次数)  5e4

    这个题目不会写,问别人的。

    这个要建26棵线段树,首先对这个字符串进行预处理,把每一个位置放到每一个字母放到它的线段树对应的位置。

    比如说 acbd     a应该放在第一棵树的1位置,c放到第三颗树,2的位置,b放到第二颗树的3号位置,以此类推。

    这个是预处理,然后就是对于操作的写法。

    每一个操作给你了一个区间,我们先计算这个区间的每一颗线段树的数量的字母数量,然后清空这个区间的每一颗线段树,

    再给定区间进行更新。

    知道了这些应该可以很好写了。

    这种题不知道算不算一种类型,用26棵线段树来解决排序问题,这里是二十六棵线段树,以后可能是建有限个线段树,对他们进行重新排序,

    升序或者降序,然后输出结果,都可以借助这种思想。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 10;
    struct node
    {
        int sum, lazy, len;
    }tree[30][maxn*10];
    char s[maxn*10];
    
    void push_up(int id)
    {
        for(int i=0;i<26;i++)
        {
            tree[i][id].sum = tree[i][id << 1].sum + tree[i][id << 1 | 1].sum;
        }
    }
    
    void build(int id,int l,int r)
    {
        for(int i=0;i<26;i++)
        {
            tree[i][id].lazy = -1;
            tree[i][id].len = r - l + 1;
        }
        if(l==r)
        {
            int x = s[l] - 'a';
            tree[x][id].sum = 1;
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        push_up(id);
    }
    
    void push_down(int id)
    {
        for(int i=0;i<26;i++)
        {
            if(tree[i][id].lazy!=-1)
            {
                int val = tree[i][id].lazy;
                tree[i][id << 1].sum = tree[i][id << 1].len*val;
                tree[i][id << 1 | 1].sum = tree[i][id << 1 | 1].len*val;
                tree[i][id << 1].lazy = tree[i][id << 1 | 1].lazy = val;
                tree[i][id].lazy = -1;
            }
        }
    }
    int a[50];
    void query(int id,int l,int r,int x,int y)
    {
        if(x<=l&&y>=r)
        {
            for(int i=0;i<26;i++)
            {
                a[i] += tree[i][id].sum;
            }
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        if (x <= mid) query(id << 1, l, mid, x, y);
        if (y > mid) query(id << 1 | 1, mid + 1, r, x, y);
    }
    
    void update(int id,int l,int r,int x,int y)//clear
    {
        if(x<=l&&y>=r)
        {
            for(int i=0;i<26;i++)
            {
                tree[i][id].sum = 0;
                tree[i][id].lazy = 0;
            }
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        if (x <= mid) update(id << 1, l, mid, x, y);
        if(y > mid) update(id << 1 | 1, mid + 1, r, x, y);
        push_up(id);
    }
    
    void updatenum(int id, int l, int r, int x, int y,int ad)//clear
    {
        if (x <= l && y >= r) {
            tree[ad][id].sum = tree[ad][id].len;
            tree[ad][id].lazy = 1;
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        if (x <= mid) updatenum(id << 1, l, mid, x, y, ad);
        if (y > mid) updatenum(id << 1 | 1, mid + 1, r, x, y, ad);
        push_up(id);
    }
    
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        scanf("%s", s + 1);
        build(1, 1, n);
        while(m--)
        {
            int l, r, k;
            scanf("%d%d%d", &l, &r, &k);
            memset(a, 0, sizeof(a));
            query(1, 1, n, l, r);
            update(1, 1, n, l, r);
            if(k==0)
            {
                for(int i=0;i<26;i++)
                {
                    if (a[i] == 0) continue;
                    updatenum(1, 1, n, r - a[i] + 1, r, i);
                    r -= a[i];
                    if (r <= 0) break;
                }
            }
            else if(k==1)
            {
                for(int  i=0;i<26;i++)
                {
                    if (a[i] == 0) continue;
                    // printf("i=%d l=%d r=%d
    ", i, l, l + a[i] - 1);
                    updatenum(1, 1, n, l, l + a[i] - 1, i);        
                    l += a[i];
                    if (l > n) break;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            memset(a, 0, sizeof(a));
            query(1, 1, n, i, i);
            for(int j=0;j<26;j++)
            {
                if(a[j])
                {
                    printf("%c", j + 'a');
                }
            }
        }
        printf("
    ");
        return 0;
    }
    /*
    10 5
    hbtngdflmj
    1 10 1
    2 9 0
    3 8 1
    4 7 0
    5 6 1
     */
    View Code
  • 相关阅读:
    html5学习系列之ef类标签
    html5学习系列之cd标签
    Java学习系列——xml学习基础
    html5学习系列——b标签
    为什么我要使用Linux,使用Linux的十个理由。
    设置Linux系统的空闲等待时间TMOUT的方法和Linux反空闲设置的两种方法
    创建动态MSSQL数据库表的方法
    SQL SERVER 自增列的方法
    XtraBackup构建MySQL主从环境的方法
    如何查看MySQL执行计划呢?
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11244629.html
Copyright © 2020-2023  润新知