Problem - E - Codeforces
- そもそも counting sort というのを初めて知った。使用制限があるが O(n) でソートできる高速ソート。それでも O(N*Q) になってしまう計算量をどう落とすか?
- 想定解法は segment tree を使うやつらしいけど、segment tree まだちゃんと勉強してないので別実装にした。(遅延評価実装面倒そうだし。)
- Codeforces #312 Div2 E. A Simple Task - kmjp's blogの解法を参照。(editorial のコメントでも似た解法の人がいた。そっちも参照。)
- 文字列を区間と文字の組と考えて counting sort してやる。解法が短くてわかりやすくてカッコイイ。
class Div2E {
public:
void solve_TLE(void) {
int N,Q;
cin>>N>>Q;
string str;
cin>>str;
REP(_, Q)
{
int x,y,d;
cin>>x>>y>>d;
--x;
--y;
vector<int> cnt(26,0);
for (int i = x; i <= y; ++i)
++cnt[str[i]-'a'];
int k = x;
REP(i, 26)
{
int j = (d==1)? i : 25-i;
if (cnt[j] == 0)
continue;
REP(ii, cnt[j])
str[k++] = j+'a';
}
}
cout<<str<<endl;
}
void solve_optim() {
int N,Q;
cin>>N>>Q;
string str;
cin>>str;
set<tuple<int,int,char>> S;
int last = 0;
FOR(i, 1, N)
{
if (str[last] == str[i])
continue;
S.emplace(last, i-1, str[last]);
last = i;
}
S.emplace(last, N-1, str[last]);
const int inf = (1<<30);
REP(_, Q)
{
int x,y,d;
cin>>x>>y>>d;
--x;
--y;
auto itX = S.lower_bound(make_tuple(x,inf,inf));
auto itY = S.lower_bound(make_tuple(y,inf,inf));
auto itYE = itY;
--itX;
--itY;
assert(get<0>(*itX) <= x && x <= get<1>(*itX));
assert(get<0>(*itY) <= y && y <= get<1>(*itY));
if (itX == itY)
continue;
vector<int> cnt(26,0);
for (auto it = itX; it != itYE; ++it)
{
int i,j;
char c;
tie(i,j,c) = *it;
i = max(x,i);
j = min(j,y);
cnt[c-'a'] += (j-i+1);
}
vector<tuple<int,int,char>> words;
int ii;
char cc;
tie(ii,ignore,cc) = *itX;
if (ii < x)
words.emplace_back(ii,x-1,cc);
tie(ignore,ii,cc) = *itY;
if (y < ii)
words.emplace_back(y+1,ii,cc);
S.erase(itX,itYE);
int k = x;
REP(i, 26)
{
int j = (d==1)? i : 25-i;
if (cnt[j] == 0)
continue;
S.emplace(k,k+cnt[j]-1,j+'a');
k += cnt[j];
}
for (auto w : words)
S.insert(w);
}
string ans;
for (auto w : S)
{
int i,j;
char c;
tie(i,j,c) = w;
ans += string(j-i+1,c);
}
cout<<ans<<endl;
}
void solve(void) {
solve_optim();
}
};