CodeForces 558E(计数排序+线段树优化)

题意:一个长度为n的字符串(只包含26个小字母)有q次操作 对于每次操作 给一个区间 和k k为1把该区间的字符不降序排序 k为0把该区间的字符不升序排序 求q次操作后所得字符串

 

思路:

该题数据规模很大 排序是关键想到计数排序,根据计数排序原理,由只有26个小写字母,需要统计区间字母的个数,还需要更新区间,想到用线段树优化,对于每个字母建一个线段树维护各字母在区间的个数。

#include <map>

#include <set>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <cstdio>

#include <vector>

#include <string>

#include <cctype>

#include <complex>

#include <cassert>

#include <utility>

#include <cstring>

#include <cstdlib>

#include <iostream>

#include <algorithm>

using namespace std;

typedef pair<int,int> PII;

typedef long long ll;

#define lson l,m,rt<<1

#define pi acos(-1.0)

#define rson m+1,r,rt<<1|1

#define All 1,N,1

#define N 100010

#define read freopen("in.txt", "r", stdin)

const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;

const int INF= 0x7ffffff;

const int mod =  1000000007;

struct tree{

    int num,l,r,lazy;

}t[30][N<<2];

int qnum[N],n,q;

char ch[N];

void  pushup(int i,int rt){

    t[i][rt].num=t[i][rt<<1].num+t[i][rt<<1|1].num;

}

void pushdown(int i,int rt){

    if(t[i][rt].lazy!=-1){

        t[i][rt<<1].num=(t[i][rt<<1].r-t[i][rt<<1].l+1)*t[i][rt].lazy;

        t[i][rt<<1].lazy=t[i][rt].lazy;

        t[i][rt<<1|1].num=(t[i][rt<<1|1].r-t[i][rt<<1|1].l+1)*t[i][rt].lazy;

        t[i][rt<<1|1].lazy=t[i][rt].lazy;

        t[i][rt].lazy=-1;

    }

}

void build(int i,int l,int r,int rt){

    t[i][rt].l=l;

    t[i][rt].r=r;

    t[i][rt].lazy=-1;

    int m=(l+r)>>1;

    if(l==r){

        t[i][rt].num=(ch[l-1]=='a'+i);

        return;

    }

    build(i,lson);

    build(i,rson);

    pushup(i,rt);

}

void update(int i,int v,int l,int r,int rt){

    if(t[i][rt].l>=l&&t[i][rt].r<=r){

        t[i][rt].num=(t[i][rt].r-t[i][rt].l+1)*v;

        t[i][rt].lazy=v;

        return;

    }

    pushdown(i,rt);

    int m=(t[i][rt].l+t[i][rt].r)>>1;

    if(l<=m)update(i,v,l,r,rt<<1);

    if(r>m)update(i,v,l,r,rt<<1|1);

    pushup(i,rt);

}

int query(int i,int l,int r,int rt){

    if(t[i][rt].l>=l&&t[i][rt].r<=r)

        return t[i][rt].num;

    pushdown(i,rt);

    int total=0;

    int mid=(t[i][rt].l+t[i][rt].r)>>1;

    if(l<=mid)total+=query(i,l,r,rt<<1);

    if(r>mid)total+=query(i,l,r,rt<<1|1);

    pushup(i,rt);

    return total;

}

void solve(){

    int l,r,w;

    for(int i=0;i<26;++i)

        build(i,1,n,1);

    while(q--){

        scanf("%d%d%d",&l,&r,&w);

        for(int i=0;i<26;++i){

            qnum[i]=query(i,l,r,1);

            update(i,0,l,r,1);

        }

        if(w==1){

            int pos=l;

            for(int i=0;i<26;++i)

            {

                if(qnum[i]>0){

                update(i,1,pos,pos+qnum[i]-1,1);

                pos+=qnum[i];

                }

            }

        }

        else{

            int pos=l;

            for(int i=25;i>=0;--i)

            {

                if(qnum[i]>0){

                update(i,1,pos,pos+qnum[i]-1,1);

                pos+=qnum[i];

                }

            }

        }

    }

     for(int i=0;i<n;++i)

    for(int j=0;j<26;++j)

    {

        if(query(j,i+1,i+1,1)){

            ch[i]='a'+j;

            break;

        }

    }

      printf("%s\n",ch);

}

int main()

{

    scanf("%d%d",&n,&q);

    scanf("%s",ch);

    solve();

return 0;

}

  

你可能感兴趣的:(codeforces)