CF558E - A Simple Task线段树

给出一个小写字母组成的字符串,然后q个操作,a,b,c ,c为0 ,将区间 [a,b] 按逆字典序排,c为1,将此区间按字典序排。用一颗线段树,维护每个节点各个字母出现的种类数,每次操作操作后,暴力将字母a组成的区间,字母b组成的区间等等,区间内所有元素更新为a,b,等等。打个lazy标记,区间更新搞下就行了。

#pragma comment(linker,"/STACK:102400000,102400000") 
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<set>
using namespace std;
typedef long long LL;
const int mod = 1000000007;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1e5 + 20;
int ch[maxn<<2][30];
int color[maxn << 2];
char str[maxn];
void up(int rt)
{
    for (int i = 0; i < 26; i++) {
        ch[rt][i] = ch[rt << 1][i] + ch[rt << 1 | 1][i];
    }
}

void down(int l, int r, int rt)
{
    if (color[rt] == -1) return;
    int mid = (l + r) >> 1;
    for (int i = 0; i < 26; i++) ch[rt << 1][i] = 0, ch[rt << 1 | 1][i] = 0;
    ch[rt << 1][color[rt]] = (mid - l + 1); ch[rt << 1 | 1][color[rt]] = r - mid;
    color[rt << 1] = color[rt << 1 | 1] = color[rt];
    color[rt] = -1;
}
void build(int l, int r, int rt)
{
    color[rt] = -1;
    if (l == r) {
        int t = str[l] - 'a';
        ch[rt][t]++;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    up(rt);
}

int ask(int L, int R, int add, int l, int r, int rt)
{
    if (L <= l&&r <= R) {
        return  ch[rt][add];
    }
    int mid = (l + r) >> 1;
    int ans = 0;
    down(l, r, rt);
    if (L <= mid) ans += ask(L, R, add, lson);
    if (R > mid) ans += ask(L, R, add, rson);
    return ans;
}



void update(int L, int R, int add, int l, int r, int rt)
{
    if (L <= l&&r <= R) {
        for (int i = 0; i < 26; i++) ch[rt][i] = 0;
        ch[rt][add] = (r - l + 1);
        color[rt] = add;
        return;
    }
    down(l, r, rt);
    int mid = (l + r) >> 1;
    if (L <= mid) update(L, R, add, lson);
    if (R > mid) update(L, R, add, rson);
    up(rt);
}

int ans = 0;
void show(int l, int r, int rt)
{
    if (l == r) {
        for (int i = 0; i < 26; i++) if (ch[rt][i]) printf("%c", i + 'a');
        return;
    }
    down(l,r,rt);
    int mid = (l + r) >> 1;
    show(lson); show(rson);
}
int cc[100];
int main()
{
    //freopen("1.in", "r", stdin);
    //freopen("2.in", "w", stdout);
    int q, n;
    int a, b, c;
    cin >> n >> q;
    scanf("%s", str);
    build(0, n-1, 1);
    while (q--) {
        scanf("%d%d%d", &a, &b, &c);
        a--; b--;
        if (c == 1) {
            for (int i = 0; i < 26; i++) cc[i + 1] = ask(a, b, i, 0, n - 1, 1);
            int ll = a;
            for (int i = 0; i < 26; i++) {
                if (cc[i + 1] == 0) continue;
                update(ll, ll + cc[i + 1] - 1, i, 0, n - 1, 1);
                ll = ll + cc[i + 1];
            }
        }
        else {
            for (int i = 0; i < 26; i++) cc[i + 1] = ask(a, b, i, 0, n - 1, 1);
            int ll = a;
            for (int i = 25; i >= 0; i--) {
                if (cc[i + 1] == 0) continue;
                update(ll, ll + cc[i + 1] - 1, i, 0, n - 1, 1);
                ll = ll + cc[i + 1];
            }
        }
    }
    show(0, n - 1, 1);
    return 0;
}

 

posted on 2015-08-13 21:04  一个西瓜  阅读(291)  评论(0编辑  收藏  举报

导航