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\n", 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("\n");
    return 0;
}
/*
10 5
hbtngdflmj
1 10 1
2 9 0
3 8 1
4 7 0
5 6 1
 */
View Code

 

posted @ 2019-07-25 15:35  EchoZQN  阅读(202)  评论(0)    收藏  举报