A Simple Task【區間排序】【線段樹】

題目鏈接:http://codeforces.com/contest/558/problem/E

題意: 給定一個字符串, m次操作, 每次操作一個區間, 0表示讓這個區間降序, 1 表示升序, 問最後字符串的樣子。

 

字符集只有26個,所以線段樹維護區間內每個字母的數量,對於排序操作就直接暴力進行區間覆蓋。

#include<bits/stdc++.h>
#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<t)  add(rs,mid+1,r,h,t,x);
    up(o);
}
int query(int o,int l,int r,int h,int t,int x) {
    if(l>=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<t)  ans += query(rs,mid+1,r,h,t,x);
    return ans;
}
int cnt[30];
int main() {
   // freopen("a.txt","r",stdin);
    ios::sync_with_stdio(0);
    cin>>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<<char(j+'a');
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章