CF240F TorCoder 题解
基本就是 CF558E。
注意到字符集很小,考虑维护出区间每个字母出现次数,然后直接重排。
显然,若出现奇数次的字母 $>1$ 个,则无法操作。
按字典序依次重排,如果剩下一个出现奇数次的字母就放在中间。
区间覆盖区间查询,线段树维护。
#include <cstdio>
#include <cctype>
#include <cstring>
#define G int m = s + t >> 1
#define C(x) memset(x, 0, sizeof x)
#define F for(int i = 0;i < 26;++i)
inline int R()
{
int r = 0;char c = getchar();while(!isdigit(c)) c = getchar();
while(isdigit(c)) r = r * 10 + c - '0', c = getchar();return r;
}
inline char I() {char c = getchar();while(!islower(c)) c = getchar();return c;}
struct T
{
T *l, *r;int s, t, x, v[26];T(int p, int q) : l(0), r(0), s(p), t(q), x(-1)
{C(v);}void u() {F v[i] = l->v[i] + r->v[i];}void d() {if(~x) {G;C(l->v);
l->v[x] = m - s + 1;C(r->v);r->v[x] = t - m;l->x = x;r->x = x;x = -1;}}
}*r;
void B(int s, int t, T *&p)
{
p = new T(s, t);if(s == t) {p->v[I() - 'a'] = 1;
return;}G;B(s, m, p->l);B(m + 1, t, p->r);p->u();
}
void M(int l, int r, int x, int s, int t, T *p)
{
if(l <= r) {if(l <= s && t <= r) {C(p->v);p->v[x] = t - s + 1;p->x = x;return;}p->
d();G;if(l <= m) M(l, r, x, s, m, p->l);if(r > m) M(l, r, x, m + 1, t, p->r);p->u();}
}
int Q(int l, int r, int x, int s, int t, T *p)
{
if(l <= r) {if(l <= s && t <= r) return p->v[x];p->d();G;int q = 0;if(l <= m)
q += Q(l, r, x, s, m, p->l);if(r > m) q += Q(l, r, x, m + 1, t, p->r);return q;}
}
void P(int s, int t, T *p) {if(s == t) {F if(p->v[i]) {putchar
(i + 'a');return;}}p->d();G;P(s, m, p->l);P(m + 1, t, p->r);}
int n, m, x, y, k, q[26];
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
n = R();m = R();B(1, n, r);while(m--)
{
x = R();y = R();C(q);k = 0;
F k += (q[i] = Q(x, y, i, 1, n, r)) & 1;
if(k > 1) continue;
F
{
M(x, x + (q[i] >> 1) - 1, i, 1, n, r);
M(y - (q[i] >> 1) + 1, y, i, 1, n, r);
x += q[i] >> 1;y -= q[i] >> 1;q[i] &= 1;
}
F if(q[i]) M(x, y, i, 1, n, r);
}
return P(1, n, r), 0;
}