2 条题解
-
0
首先判断能否构成回文串 对于前 ⌊n/2⌋个字符,若每种字符出现次数恰好为对应的一半, 那么就把右半部分对称成左半部分的样子即可,若左边相邻两个字符交换, 逆序对个数只会 ±1,而右半部分的逆序对只会 ∓1,恰好抵消 否则贪心的将右边靠左且多的字符往左边移,这样影响的逆序对数是最少的 然后树状数组求逆序对即可
#include <bits/stdc++.h> using namespace std; #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; } -
0
/* 首先判断能否构成回文串 对于前 ⌊n/2⌋个字符,若每种字符出现次数恰好为对应的一半, 那么就把右半部分对称成左半部分的样子即可,若左边相邻两个字符交换, 逆序对个数只会 ±1,而右半部分的逆序对只会 ∓1,恰好抵消 否则贪心的将右边靠左且多的字符往左边移,这样影响的逆序对数是最少的 然后树状数组求逆序对即可 */ #include <bits/stdc++.h> using namespace std; #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; }
- 1
信息
- ID
- 2932
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者