[线段树]JZOJ 5829 string

Description

给定一个由小写字母组成的字符串 s。有 m 次操作,每次操作给 定 3 个参数 l,r,x。如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r] 降序排序。你需要求出最终序列。 
 

Input

第一行两个整数 n,m。第二行一个字符串 s。接下来 m 行每行三 个整数 l,r,x。

Output

一行一个字符串表示答案。 
 

Sample Input

5 2
cabcd
1 3 1
3 5 0 

Sample Output

abdcc
 

Data Constraint

对于 40%的数据,n,m<=1000。
对于 100%的数据,n,m<=100000

分析

本来想了一波区间k大还是什么玩意儿然后嘀咕怎么提高组也考这个

结果赛后才看到只有小写字母

那用线段树维护啊,如果区间只有一种字母就标记其他差不多

#include <iostream>
#include <cstdio>
#include <memory.h>
#define l(p) t[p].l
#define r(p) t[p].r
#define c(p) t[p].c
using namespace std;
const int N=100001;
struct Node {
    int l,r,c;
}t[4*N];
int aoq[26];
char s[N];
int n,m;

void Build(int x,int l,int r) {
    l(x)=l;r(x)=r;
    if (l==r) {
        c(x)=s[l]-'a'+1;
        return;
    }
    int mid=l+r>>1;
    Build(x*2,l,mid);Build(x*2+1,mid+1,r);
    c(x)=c(x*2)*(c(x*2)==c(x*2+1));
}

void Change(int x,int l,int r,int dat) {
    if (l<=l(x)&&r(x)<=r||c(x)==dat) {
        c(x)=dat;
        return;
    }
    int mid=l(x)+r(x)>>1;
    if (c(x)) c(x*2)=c(x*2+1)=c(x),c(x)=0;
    if (l<=mid) Change(x*2,l,r,dat);
    if (r>mid) Change(x*2+1,l,r,dat);
    c(x)=c(x*2)*(c(x*2)==c(x*2+1));
}

void Query(int x,int l,int r) {
    if (l>r(x)||l(x)>r) return;
    if (l<=l(x)&&r(x)<=r&&c(x)) {
        aoq[c(x)-1]+=r(x)-l(x)+1;
        return;
    }
    if (c(x)) c(x*2)=c(x*2+1)=c(x);
    int mid=l(x)+r(x)>>1;
    if (l<=mid) Query(x*2,l,r);
    if (r>mid) Query(x*2+1,l,r);
}

void Pushdown(int x) {
    if (c(x)) {
        for (int i=l(x);i<=r(x);i++) s[i]=c(x)+'a'-1;
        return;
    }
    Pushdown(x*2);Pushdown(x*2+1);
}

int main() {
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    Build(1,1,n);
    while (m--) {
        int l,r,c;
        scanf("%d%d%d",&l,&r,&c);
        memset(aoq,0,sizeof aoq);
        Query(1,l,r);
        if (c) {
            int ll=l;
            for (int i=0;i<26;i++)
            if (aoq[i]) Change(1,ll,ll+aoq[i]-1,i+1),ll+=aoq[i];
        }
        else {
            int ll=l;
            for (int i=25;i>=0;i--)
            if (aoq[i]) Change(1,ll,ll+aoq[i]-1,i+1),ll+=aoq[i];
        }
    }
    Pushdown(1);
    for (int i=1;i<=n;i++) printf("%c",s[i]);
    fclose(stdin);fclose(stdout);
}
View Code

 

posted @ 2018-08-19 07:55  Vagari  阅读(336)  评论(0编辑  收藏  举报