tsinsen A1043. 完美的代价
2016-02-26 19:29
363 查看
A1043. 完美的代价
时间限制:1.0s 内存限制:512.0MB
总提交次数:1985
AC次数:446 平均分:44.86
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5
mamad
样例输出
3
题解:先从简单的说起,如何判断Impossible,如果长度为偶数,那么所有出现过的字符的个数必须都是偶数,这样才能保证一一对应;如果是奇数,那么允许有一个字符的个数是奇数。如果上述条件不满足,直接输出Impossible就可以了。
如何求最少的交换次数呢?首先先把字符串翻转,然后让原串与翻转串相同的字符一一对应,例如mamad ,翻转后为damam,但是得到的数列不是54321,而应该是52143,也就是说原字符串中某个字符第一次对应翻转字符串的第一次出现,得到数列后求一下该数列的逆序对数除以2即为答案。
为什么呢?因为把原串转成翻转串的过程中必经过是回文串的时刻。
时间限制:1.0s 内存限制:512.0MB
总提交次数:1985
AC次数:446 平均分:44.86
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5
mamad
样例输出
3
题解:先从简单的说起,如何判断Impossible,如果长度为偶数,那么所有出现过的字符的个数必须都是偶数,这样才能保证一一对应;如果是奇数,那么允许有一个字符的个数是奇数。如果上述条件不满足,直接输出Impossible就可以了。
如何求最少的交换次数呢?首先先把字符串翻转,然后让原串与翻转串相同的字符一一对应,例如mamad ,翻转后为damam,但是得到的数列不是54321,而应该是52143,也就是说原字符串中某个字符第一次对应翻转字符串的第一次出现,得到数列后求一下该数列的逆序对数除以2即为答案。
为什么呢?因为把原串转成翻转串的过程中必经过是回文串的时刻。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; int a[8100],b[8100],n,m,ans,ch[30][8100],p[8100],r[8100]; int id[30]; void pd() { if (n%2==0) { for (int i=1;i<=26;i++) if (id[i]%2!=0) { printf("Impossible\n"); exit(0); } } else { int k=0; for (int i=1;i<=26;i++) if (id[i]%2!=0) k++; if (k>1) { printf("Impossible\n"); exit(0); } } } void mergesort(int s,int t) { if (s==t) return; int mid=(s+t)/2; mergesort(s,mid); mergesort(mid+1,t); int i=s; int j=mid+1; int mp=s; int k[8100]; memset(k,0,sizeof(k)); while (i<=mid&&j<=t) { if (r[i]<r[j]) k[mp]=r[i],i++,mp++; else k[mp]=r[j],ans+=mid-i+1,j++,mp++; } for (int l=i;l<=mid;l++) k[mp]=r[l],mp++; for (int l=j;l<=t;l++) k[mp]=r[l],mp++; for (int l=s;l<=t;l++) r[l]=k[l]; } int main() { memset(id,0,sizeof(id)); scanf("%d\n",&n); for (int i=1;i<=n;i++) { char c; c=getchar(); int cc=c-96; id[cc]++; ch[cc][0]++; ch[cc][ch[cc][0]]=i; a[i]=cc; b[n-i+1]=cc; } pd(); for (int i=1;i<=n;i++) { p[b[i]]++; r[i]=ch[b[i]][p[b[i]]]; } /*for (int i=1;i<=n;i++) printf("%d ",r[i]); cout<<endl;*/ mergesort(1,n); printf("%d",ans/2); return 0; }
相关文章推荐
- shell 常用命令
- 看了《小黄人》这么久却没看到这一层!真不想一辈子都当码农!
- mac下mysql中文乱码
- robotium注入和查找事件源码浅析
- MyEclipse10 Servers窗口出现“Could not create the view: An unexpected exception was thrown”解决办法
- Poj 1201 Intervals
- GDKOI2016Day1第二题 不稳定的传送门 解题报告
- c# 抗变 协变
- PHP 表单验证
- VS 2013搭建PCL,不需要Cmake
- 单链表的建立与打印
- redis 集合命令
- codeforces 629C Famil Door and Brackets(dp)
- 学而不思则罔
- iOS内存分配
- 求树的叶子结点的个数
- Android:ScrollView和SwipeRefreshLayout高度测量
- 创建安卓应用的 30 个经验教训
- iOS上传照片旋转90度解决方法
- 部署搭建 puppet