Description
给定一个长度为 n n 的小写字母序列,有个操作,每次将第 li l i 个字母到第 ri r i 个字母排成升序或倒序,求最后得到的序列。
Solution
法一
由于只有26种元素,考虑用线段树维护每个节点所包含的每个字母的个数以及该区间内是降序还是升序或者乱序,直接维护即可
法二
考虑用set维护,一开始每一个字母都是一个独立的集合,每次操作将两端的集合暴力拆开,将中间的字母集合合并
时间复杂度
O(n×log2n×26) O ( n × l o g 2 n × 26 ) 或 O(n×log2n+n×26) O ( n × l o g 2 n + n × 26 )
Code
法一
#10916296 | HanYi's solution for [CodeForces-558E]
Status Accepted
Time 312ms
Memory 43948kB
Length 4298
Lang GNU G++11 5.1.0
Submitted 2017-10-03 15:45:23
Shared
RemoteRunId 30961190
Select 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;
}