CodeForces - 558E A Simple Task (计数排序 线段树)

This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.

Output the final string after applying the queries.

Input
The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively.

Next line contains a string S itself. It contains only lowercase English letters.

Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, ).

Output
Output one line, the string S after applying the queries.

Examples
Input
10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1
Output
cbcaaaabdd
Input
10 1
agjucbvdfk
1 10 1
Output
abcdfgjkuv
这里写图片描述

题意很简单,就是给你个字符串,然后又q次操作,每次操作有i,j,k三个值,如果k为0,就把i,j区间的字符降序排序,如果k = 1,就将i,j区间的字符串升序排序,最后输出这个字符串。下标从1开始。

直接暴力显然会超时,这个题因为只有26个小写字母,所以我们可以利用区间查询出这个区间每个字符的个数,先把这个区间所有字符的个数都更新为0,即相当于删去所有字符。然后再按照升或降的顺序从开头存放,即从新填放,这里面对于区间的操作我们就用到了线段树。

代码如下:

#include<bits/stdc++.h>

using namespace std;
#define lson (k*2)
#define rson (k*2+1)
const int MAX = 100010;
const int MAX_V = 28;
class Node{
public:
    int l,r,v[MAX_V];
    Node();
    int mid(){
        return (l+r)/2;
    }
    int len(){
        return r-l+1;
    }
};
int Lazy[MAX*4][MAX_V];
int N,Q;
char str[MAX];
Node tree[MAX*4];
void PushUp(int k,int id){
    tree[k].v[id] = tree[lson].v[id] + tree[rson].v[id];
}
void PushDown(int k,int id){
    if(Lazy[k][id] != -1){
        int value = Lazy[k][id];
        tree[lson].v[id] = tree[lson].len()*value;
        tree[rson].v[id] = tree[rson].len()*value;
        Lazy[lson][id] = value;
        Lazy[rson][id] = value;
    }
    Lazy[k][id] = -1;
}
void Build(int L,int R,int k){
    tree[k].l = L;
    tree[k].r = R;
    if(L == R){
        int id = str[L]-'a';
        tree[k].v[id] = 1;
        return;
    }
    int mid = (L+R)/2;
    Build(L,mid,lson);
    Build(mid+1,R,rson);
    for(int i=0;i<26;++i)
        PushUp(k,i);
}
void Update(int L,int R,int add,int k,int id){
    if(L <= tree[k].l && tree[k].r <= R){
        tree[k].v[id] = add*tree[k].len();
        Lazy[k][id] = add;
        return;
    }
    PushDown(k,id);
    int mid = tree[k].mid();
    if(L <= mid)    Update(L,R,add,lson,id);
    if(R > mid) Update(L,R,add,rson,id);
    PushUp(k,id);
}
int Query(int L,int R,int k,int id){
    if(L <= tree[k].l && tree[k].r <= R)
        return tree[k].v[id];
    PushDown(k,id);
    int res = 0;
    int mid = tree[k].mid();
    if(L <= mid)    res += Query(L,R,lson,id);
    if(R > mid)     res += Query(L,R,rson,id);
    return res;
}
void Display(){
    for(int i=1;i<=N;++i){
        for(int id=0;id<26;++id){
            if(Query(i,i,1,id)){
                printf("%c",'a'+id);
            }
        }
    }
    printf("\n");
}
void Show(int *bas){
    for(int id=0;id<26;++id){
        printf("%d ",bas[id]);
    }
    printf("\n");
}
int main(void){
    //这里要把lzay设置为-1,因为更新值可能为0,注意。
    memset(Lazy,-1,sizeof(Lazy));
    scanf("%d%d",&N,&Q);
    scanf("%s",str+1);
    Build(1,N,1);
    int u,v,w;
    int bas[MAX_V];//存储每个字符的个数
    for(int i=1;i<=Q;++i){
        scanf("%d%d%d",&u,&v,&w);
        if(w == 0){
            //查询该区间每个字符的个数。
            for(int id=0;id<26;++id){
                bas[id] = Query(u,v,1,id);
                Update(u,v,0,1,id);
            }
            int l=u,r;
            //0表示降序,即从后往前更新对应区间的字符。
            for(int id=25;id>=0;--id){
                if(bas[id]){
                    r = l+bas[id]-1;
                    Update(l,r,1,1,id);
                    l += bas[id];
                }
            }
        }
        else{
            for(int id=0;id<26;++id){
                bas[id] = Query(u,v,1,id);
                Update(u,v,0,1,id);
            }
            int l=u,r;
            for(int id=0;id<26;++id){
                if(bas[id]){
                    r = l + bas[id]-1;
                    Update(l,r,1,1,id);
                    l += bas[id];
                }
            }
        }

    }
    Display();
    return 0;
}
Node::Node(){
    l = r = 0;
    memset(v,0,sizeof(v));
}

猜你喜欢

转载自blog.csdn.net/zhao5502169/article/details/81390673