2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)
2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)
https://www.luogu.com.cn/problem/P5041
题意:
给一个字符串 \(S\) ,每次交换相邻两个位置的字符,使得 \(S\) 变成回文串,求最小交换次数。
分析:
首先,对于一个回文串,最多有一个字符出现次数为奇数,这个字符必须放在回文串的最中间,剩下的字符两边放就行。
对于一个字符 \(x\) ,一共在回文串中出现了 \(sizei_x\) 次,每次出现的位置为 \(pos_{x_i}\) 。这 \(sizei_x\) 个字符分布在中间字符(也可能没有中间字符,如果这个字符串长度为偶数)两侧,可想而知,每次移动最左边和最右边的两个字符把它们固定在对称的位置上是最优的,不然就像蓝书第一题,两只蚂蚁来回掉头就是两只蚂蚁一直前进一样。
好吧,假设一下,设字符 \(x\) 一共有4个,分别在 \(pos_{x_1}\) 、 \(pos_{x_2}\) 、 \(pos_{x_3}\) 、 \(pos_{x_4}\) ,且 \(pos_{x_1}<pos_{x_2}<pos_{x_3}<pos_{x_4}\) ,它们可以被固定在两个轴对称的位置 \(a\) 与 \(\alpha\) 、 \(b\) 与 \(\beta\) ,且 \(a<b<\beta<\alpha\) 。如果把 \(pos_{x_2}\) 与 \(pos_{x_3}\) 这两个位置上的 \(x\) 固定到 \(a\) 与 \(\alpha\) ,那么 \(pos_{x_2}\) 上的 \(x\) 一定会和 \(pos_{x_1}\) 上的交换,不如直接从 \(pos_{x_1}\) 开始交换,对于 \(pos_{x_3}\) 上的 \(x\) 同理。
对于两个相邻位置上的字符 \(x\) 与 \(y\) , \(x\) 在 \(y\) 的左边。如果离 \(x\) 最远的另一个相同的字符包含了离 \(y\) 最远的另一个相同字符,即 xyyx ,那么先选 \(x\) 再选 \(y\) 是最优的。如果两个字符交叉出现即 xyxy ,对结果并没有影响。如果两个字符分别重复出现即 xxyy ,对结果依旧没影响。所以按照顺序对字符进行排序最优。
至于一个字符究竟交换了几次?咱把原位置在排完序后的出现次序记录下来,求个逆序对~
树状数组,你值得拥有~
(咱是不是做过同类型的题?/疑惑)
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
#define int long long
const int N=1e6+10;
int n,a[N],fin[N],t[N],vis[N],top[N],len;
vector<int>pos[30];
inline int lowbit(int x){
return x&-x;
}
inline void add(int x,int k){
for(int i=x;i<=n+5;i+=lowbit(i))t[i]+=k;
}
inline int query(int x){
int ans=0;
for(int i=x;i>0;i-=lowbit(i))ans+=t[i];
return ans;
}
signed main(){
IOS;
string s;cin>>s;
n=s.length();
int cnt=0;
for(int i=1;i<=n;i++){
a[i]=s[i-1]-'A'+1;
pos[a[i]].push_back(i);
if(pos[a[i]].size()&1)++cnt;
else --cnt;
}
//if(n%2==0&&cnt)return puts("-1"),0;
//if(n%2==1&&cnt>1)return puts("-1"),0;
if(cnt){
int now=0;
for(int i=1;i<=26;i++)if(pos[i].size()&1){
now=pos[i][pos[i].size()/2];
vis[now]=1;
fin[n/2+1]=now;
//cout<<3/2<<endl;
//cout<<now<<" "<<pos[i][0]<<" "<<pos[i][1]<<" "<<pos[i][2]<<" "<<pos[i][3]<<" "<<pos[i].size()<<endl;
break;
}
}
for(int i=1;i<=n/2+len;i++){
if(vis[i]){
++len;continue;
}
int x=a[i];
vis[i]=vis[pos[x].back()]=1;
fin[i-len]=i;fin[n-(i-len)+1]=pos[x].back();
pos[x].pop_back();
}
//for(int i=1;i<=n;i++)cout<<fin[i]<<" ";cout<<endl;
int tot=0;
for(int i=n;i>=1;i--){
tot+=query(fin[i]);
add(fin[i],1);
}
cout<<abs(tot);
return 0;
}
2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)的更多相关文章
- poj3067 Japan 树状数组求逆序对
题目链接:http://poj.org/problem?id=3067 题目就是让我们求连线后交点的个数 很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序 那么答案即为逆序对的个数 ...
- Palindrome - URAL - 1297(求回文串)
题目大意:RT 分析:后缀数组求回文串,不得不说确实比较麻烦,尤其是再用线段数进行查询,需要注意的细节地方比较多,比赛实用性不高......不过练练手还是可以的. 线段数+后缀数组代码如下: ...
- 马拉车,O(n)求回文串
马拉车,O(n)求回文串 对整个马拉车算法步骤做个总结: 第一步:将每个原字母用两个特殊字符包围如: aaa --> #a#a#a# abab -->#a#b#a#b 同时可以由这个翻倍的 ...
- HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number ...
- POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8807 Accepted ...
- Codeforces 486E LIS of Sequence --树状数组求LIS
题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i] ...
- POJ2299Ultra-QuickSort(归并排序 + 树状数组求逆序对)
树状数组求逆序对 转载http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html 转载: 树状数组,具体的说是 离散化+树 ...
- hdu 4217 Data Structure? 树状数组求第K小
Data Structure? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- poj 2985 The k-th Largest Group 树状数组求第K大
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8353 Accepted ...
随机推荐
- 内网渗透----Windows下信息收集
一.基础信息收集 使用systeminfo命令查看操作系统版本.架构.补丁情况 Windows-Exploit-Suggester-master -u 参数升级并将数据库下载至本地: -i 参数指定系 ...
- 《前端运维》二、Nginx--3静态资源服务、跨域与其他
一.静态资源服务 首先,静态资源一般是指客户端发送请求到Web服务器,web服务器从内存中取得相应的文件,返回给客户端,客户端解析并渲染出来.动态资源呢,则是由客户端发起请求,先交由web容器,web ...
- 你了解过Servlet3.0吗?
Servlet3.0相对于Servlet2.0来说最大的改变是引入了Annotation标注来取代xml配置,用于简化web应用的开发和部署.最主要几项特性: 1. 新增的注解支持:该版本新增了若干注 ...
- 服务注册和发现是什么意思?Spring Cloud 如何实现?
当我们开始一个项目时,我们通常在属性文件中进行所有的配置.随着越来越多的服务开发和部署,添加和修改这些属性变得更加复杂.有些服务可能会下降,而某些位置可能会发生变化.手动更改属性可能会产生问题.Eur ...
- Java 中能创建 volatile 数组吗?
能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不 是整个数组.我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护, 但是如果多个线程同时改变数 ...
- mybatis源码之我见
以前一直想看mybatis的源代码,但是一直没找到入口(傻),最近看教程,有些感悟. 和起以前一样,关键代码我会用红色标记. 首先,先贴下我的dao和mapper,代码很简单,和平时写的hello w ...
- 13_Invariance Principle_LaSalle's Theorem_不变性原理
- 关于个人开源项目(vue app)的一些总结
关于个人开源项目(vue app)的一些总结 项目地址 https://github.com/BYChoo/record 项目简介 此项目名叫:Record.是以Vue全家桶(vue,vue-rout ...
- visio2019专业版激活码
这里面有 : 最新Project2019+ Visio2019专业增强版和专业版永久激活密钥分享 (weibo.com)
- 关于根据数据反选checkbox
前两天完成了一个连接hbase数据库的mis系统,mis系统中经常需要修改功能,复选框.多选框等等的自动勾选,感觉很麻烦,在此记录一下修改功能checkbox自动选中. 例子: <div cla ...