CF 558E A Simple Task (线段树)

来源:互联网 发布:这样更换ubuntu的主题 编辑:程序博客网 时间:2024/06/11 11:44

Description

给定一个长度为n的小写字母序列,有m个操作,每次将第li个字母到第ri个字母排成升序或倒序,求最后得到的序列。

Solution

法一

由于只有26种元素,考虑用线段树维护每个节点所包含的每个字母的个数以及该区间内是降序还是升序或者乱序,直接维护即可

法二

考虑用set维护,一开始每一个字母都是一个独立的集合,每次操作将两端的集合暴力拆开,将中间的字母集合合并

时间复杂度

O(n×log2n×26)O(n×log2n+n×26)

Code

法一

#10916296 | HanYi's solution for [CodeForces-558E]Status  AcceptedTime    312msMemory  43948kBLength  4298Lang    GNU G++11 5.1.0Submitted   2017-10-03 15:45:23Shared  RemoteRunId 30961190Select Code//LuanGao#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<set>#define For(i , j , k) for (int i = (j) , _##end_ = (k) ; i <= _##end_ ; ++ i)#define Fordown(i , j , k) for (int i = (j) , _##end_ = (k) ; i >= _##end_ ; -- i)#define Set(a , b) memset(a , b , sizeof(a))#define pb push_back#define lc (t << 1)#define rc (t << 1 | 1)#define mid ((l + r) >> 1)#define INF (0x3f3f3f3f)#define Mod (1000000007)using namespace std;typedef long long LL;template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; }int _ , __;char c_;inline int read(){    for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1;    for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);    return _ * __;}inline void file(){#ifndef ONLINE_JUDGE    freopen("string.in" , "r" , stdin);    freopen("string.out" , "w" , stdout);#endif}const int maxn = 100010;struct Item{    int a[27] , type;    //type = 0: LuanXu    //type = 1: ShengXu    //type = 2: JiangXu}tr[maxn * 4] , d , tmp;Item operator + (const Item &A , const Item &B){    Item C;    C.type = 0;    For(i , 0 , 25)        C.a[i] = A.a[i] + B.a[i];    return C;}inline void clear(int t){    For(i , 0 , 25)        tr[t].a[i] = 0;}int n , m , x , y , type;char s[maxn];inline void maintain(int t) { tr[t] = tr[lc] + tr[rc]; }inline void pushdown(int t , int l , int r){    tmp = tr[t];    if (tmp.type == 1 || tmp.type == 2)        tr[lc].type = tr[rc].type = tmp.type;    int res = mid - l + 1;    if (tr[t].type == 1)    {        clear(lc);        For(i , 0 , 25)        {            if (tmp.a[i] <= res)            {                tr[lc].a[i] = tmp.a[i];                res -= tmp.a[i];                tmp.a[i] = 0;            }            else            {                tmp.a[i] -= res;                tr[lc].a[i] = res;                res = 0;            }        }        tr[rc] = tmp;    }    else    if (tr[t].type == 2)    {        clear(lc);        Fordown(i , 25 , 0)        {            if (tmp.a[i] <= res)            {                tr[lc].a[i] = tmp.a[i];                res -= tmp.a[i];                tmp.a[i] = 0;            }            else            {                tmp.a[i] -= res;                tr[lc].a[i] = res;                res = 0;                break;            }        }        tr[rc] = tmp;    }}void build(int t , int l , int r){    if (l == r)    {        tr[t].a[s[l] - 97] = 1;        return ;    }    build(lc , l , mid);    build(rc , mid + 1 , r);    maintain(t);}Item query(int t , int l , int r){    if (x <= l && r <= y)        return tr[t];    pushdown(t , l , r);    if (x > mid)        return query(rc , mid + 1 , r);    if (y <= mid)        return query(lc , l , mid);    return query(rc , mid + 1 , r) + query(lc , l , mid);}void update1(int t , int l , int r){    if (x <= l && r <= y)    {        tr[t].type = 1;        int res = r - l + 1;        clear(t);        For(i , 0 , 25)        {            if (d.a[i] <= res)            {                tr[t].a[i] = d.a[i];                res -= d.a[i];                d.a[i] = 0;            }            else            {                d.a[i] -= res;                tr[t].a[i] = res;                res = 0;                break;            }        }        return ;    }    pushdown(t , l , r);    if (x <= mid)        update1(lc , l , mid);    if (y > mid)        update1(rc , mid + 1 , r);    tr[t].type = 0;    maintain(t);}void update2(int t , int l , int r){    if (x <= l && r <= y)    {        tr[t].type = 2;        int res = r - l + 1;        clear(t);        Fordown(i , 25 , 0)        {            if (d.a[i] <= res)            {                tr[t].a[i] = d.a[i];                res -= d.a[i];                d.a[i] = 0;            }            else            {                d.a[i] -= res;                tr[t].a[i] = res;                res = 0;                break;            }        }        return ;    }    pushdown(t , l , r);    if (x <= mid)        update2(lc , l , mid);    if (y > mid)        update2(rc , mid + 1 , r);    tr[t].type = 0;    maintain(t);}void print(int t , int l , int r){    if (l == r)        For(i , 0 , 25)            if (tr[t].a[i])            {                putchar(i + 97);                return;            }    if (tr[t].type == 1)    {        For(i , 0 , 25)            For(j , 1 , tr[t].a[i])                putchar(i + 97);        return ;    }    if (tr[t].type == 2)    {        Fordown(i , 25 , 0)            For(j , 1 , tr[t].a[i])                putchar(i + 97);        return ;    }    pushdown(t , l , r);    print(lc , l , mid);    print(rc , mid + 1 , r);}int main(){    file();    n = read();    m = read();    scanf("%s" , s + 1);    build(1 , 1 , n);    while (m --)    {        x = read();        y = read();        type = read();        d = query(1 , 1 , n);        if (type)            update1(1 , 1 , n);        else            update2(1 , 1 , n);    }    print(1 , 1 , n);    putchar('\n');    return 0;}
阅读全文
0 0
原创粉丝点击