BZOJ 1279 및 1437 : Sgu325 회문

있는지 회문 시퀀스는 제 결정된 구성
전면 \ (\ lfloor \ FRAC {n은 } {2} \ rfloor \) 횟수는 각 문자의 정확히 절반에 대응 나타나는 경우 문자가, 그 왼쪽에 대칭의 오른쪽 반에 넣고 상기 캔의 반 등 좌측 인접하는 2 개 개의 문자를 교환하는 경우, 수만의 역순 \ (\ PM 1 \) 동안의 역순의 오른쪽 반에만, \ (\ MP 1 \) 바로 상쇄
그렇지 욕심 많은 문자의 오른쪽은 영향력의 수의 역순으로, 왼쪽으로 이동 왼쪽 최소화
하고 펜윅 트리 순서를 반대로하고자하는

#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;
}

추천

출처www.cnblogs.com/Mrzdtz220/p/12343475.html