BZOJ 1279 & 1437: Sgu325 palindrome

Palindrome sequence constituting the first determined whether
the front \ (\ lfloor \ frac {n } {2} \ rfloor \) characters, if the number of times each character appears exactly corresponding to half, then put into the right half of the left symmetry like half of the can, if left adjacent two characters exchange, only in reverse order of the number \ (\ PM 1 \) , while the right half of the reverse order of only \ (\ MP 1 \) , just to offset
otherwise greedy and left the right side of many characters shift to the left, in reverse order of the number of such influence is minimal
and Fenwick tree seeking to reverse order

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
#define ll long long
#define db double
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int cnt=1,head[N],to[N*2],ne[N*2];void addd(int u,int v){to[++cnt]=v;ne[cnt]=head[u];head[u]=cnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int cnt=1,head[N],to[N*2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++cnt]=v;ne[cnt]=head[u];c[cnt]=w;head[u]=cnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])

const int N = 1e5 + 7;
char s[N];
int cnt[28], pos[28][N], half[28], a[N], b[N], n, tree[N];
inline int lowbit(int x) { return x & -x; }
void add(int x) {
    assert(x);
    for (int i = x; i <= n; i += lowbit(i)) tree[i]++;
}
int query(int x) {
    int ans = 0;
    for (int i = x; i; i -= lowbit(i)) 
        ans += tree[i]; 
    return ans;
}

void solve() {
    memset(cnt, 0, sizeof(cnt));
    scanf("%s", s + 1);
    n = strlen(s + 1);
    memset(tree, 0, sizeof(int) * (n + 2));
    rep (i, 1, n + 1) {
        int c = s[i] - 'a';
        cnt[c]++;
        pos[c][cnt[c]] = i;
    }
    int tol = 0, mid_alp = -1;
    rep (i, 0, 26) {
        if (cnt[i] & 1) tol++, mid_alp = i;
        half[i] = cnt[i] / 2;
    }
    if (n % 2 == 0) {
        if (tol) { puts("Impossible"); return; }
    } else if (tol != 1) {
        puts("Impossible"); return;
    }
    int cur = 1;
    int mi = n / 2;
    rep (i, 1, mi + 1) {
        while (!half[s[cur] - 'a']) cur++;
        a[i] = cur; half[s[cur++] - 'a']--;
    }
    if (n & 1) {
        a[mi + 1] = pos[mid_alp][cnt[mid_alp] / 2 + 1];
        //assert(pos[mid_alp][cnt[mid_alp] / 2 + 1] == cnt[mid_alp] / 2 + 1);
        per(i, 1, mi + 1) {
            int c = s[a[mi - i + 1]] - 'a';
            a[i + mi + 1] = pos[c][cnt[c]--];
        }
    } else {
        per(i, 1, mi + 1) {
            int c = s[a[mi - i + 1]] - 'a';
            a[i + mi] = pos[c][cnt[c]--];
        }
    }
    rep (i, 1, n + 1) b[a[i]] = i;
    long long ans = 0;
    per (i, 1, n + 1) ans += query(b[i]), add(b[i]);
    printf("%lld\n", ans);
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--)
        solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/Mrzdtz220/p/12343475.html