A Simple Task【区间排序】【线段树】

题目链接:http://codeforces.com/contest/558/problem/E

题意: 给定一个字符串, m次操作, 每次操作一个区间, 0表示让这个区间降序, 1 表示升序, 问最后字符串的样子。

 

字符集只有26个,所以线段树维护区间内每个字母的数量,对于排序操作就直接暴力进行区间覆盖。

#include
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ls (o<<1)
#define rs (o<<1|1)
#define mid (l+r>>1)
#define ll long long
using namespace std;
const int N = 1e5+100;
int i,n,m,h,t;
char s[N];
struct node{
    int v[30],lz,len;
}T[4*N];
void up(int o) {
    rep(i, 0, 25) T[o].v[i] = T[ls].v[i]+T[rs].v[i];
}
void build(int o,int l,int r) {
    T[o].len = r-l+1;
    T[o].lz = -1;
    if(l==r) {
        T[o].v[s[l]-'a']++;
        return;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    up(o);
}
void down(int o) {
    rep(i, 0, 25) {
        T[ls].v[i] = 0;
        T[rs].v[i] = 0;
    }
    int lz = T[o].lz;
    T[ls].v[lz] = T[ls].len;
    T[rs].v[lz] = T[rs].len;
    T[ls].lz = T[rs].lz = lz;
    T[o].lz = -1;
}
void add(int o,int l,int r,int h,int t,int x) {
    if(l>=h&&r<=t){
        rep(i, 0, 25) T[o].v[i] = 0;
        T[o].v[x] = T[o].len;
        T[o].lz = x;
        return ;
    }
    if(T[o].lz!=-1) down(o);
    if(mid>=h) add(ls,l,mid,h,t,x);
    if(mid=h&&r<=t) return T[o].v[x];
    if(T[o].lz!=-1) down(o);
    int ans = 0;
    if(mid>=h) ans += query(ls,l,mid,h,t,x);
    if(mid>n>>m;
    cin>>s+1;
    build(1,1,n);

    rep(i, 1, m) {
        int l,r,oper;
        cin>>l>>r>>oper;
        rep(j, 0, 25) cnt[j] = query(1,1,n,l,r,j);
        if(oper) {
            int now = l;
            rep(j, 0, 25) {
                if(cnt[j]==0) continue;
                add(1,1,n,now,now+cnt[j]-1,j);
                now += cnt[j];
            }
        }
        else {
            int now = l;
            per(j, 25, 0) {
                if(cnt[j]==0) continue;
                add(1,1,n,now,now+cnt[j]-1,j);
                now += cnt[j];
            }
        }
    }
    rep(i, 1, n) rep(j, 0, 25) if(query(1,1,n,i,i,j)) cout<

 

你可能感兴趣的:(区间问题,线段树)