欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-04 09:34:18
...

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
CodeForces - 558E A Simple Task (计数排序 线段树)

题意很简单,就是给你个字符串,然后又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));
}
相关标签: codeforces