[haoi2009]求回文串

所谓回文串,就是对于给定的字符串,正着读和反着读都一样,比如ABCBA就是一个回文串,ABCAB则不是。我们的目标是对于任意输入的字符串,不断将第i个字符和第i+1个字符交换,使得该串最终变为回文串。求最少交换次数。

题解:

有一种做法是贪心;

就是每次找到最左端的字符,然后找到这序列中最右边的一样的字符,然后把这个字符移过去,然后把最左端右移,继续以上操作;

最后的答案就是每次的移动步数加起来;

要吐槽的是,window下I64d不要忘了......

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define FILE "dealing"
#define LL long long
#define up(i,j,n) for(LL i=j;i<=n;i++)
#define pii pair<LL,LL>
#define piii pair<LL,pair<LL,LL> >
template<typename T> inline bool chkmin(T &a,T b){return a>b?a=b,true:false;}
template<typename T> inline bool chkmax(T &a,T b){return a<b?a=b,true:false;}
namespace IO{
    char *fs,*ft,buf[1<<15];
    inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    inline LL read(){
        LL x=0;LL ch=gc();bool f=0;
        while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();}
        while(ch<=‘9‘&&ch>=‘0‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();}
        return f?-x:x;
    }
}using namespace IO;
namespace OI{
    const LL maxn(1010000),mod(10000);
    char s[maxn];LL n;
    vector<LL> g[27];
    bool vis[maxn];
    LL c[maxn];
    inline LL lowbit(LL x){return x&-x;}
    inline void add(LL x,LL y){while(x<=n){c[x]+=y;x+=lowbit(x);}}
    inline LL get(LL x){LL sum=0;while(x>0)sum+=c[x],x-=lowbit(x);return sum;}
    void slove(){
        scanf("%s",s+1);
        n=strlen(s+1);LL x=0,cnt=0;
        up(i,1,n)x=x^(1<<(s[i]-‘A‘));
        for(LL i=0;i<26;i++)if(x&(1<<i))cnt++;
        if(cnt>1){printf("-1\n");return;}
        up(i,1,n)g[s[i]-‘A‘].push_back(i);
        up(i,1,n)add(i,1);
        LL ans=0;
        up(i,1,n){
            if(vis[i])continue;
            LL v=g[s[i]-‘A‘][g[s[i]-‘A‘].size()-1];
            if(i==v)ans+=(get(n)-get(i))/2;
            else ans+=get(n)-get(v);
            add(i,-1);add(v,-1);
            vis[i]=vis[v]=1;
            g[s[i]-‘A‘].erase(g[s[i]-‘A‘].end()-1);
        }
        printf("%I64d\n",ans);
    }
}
int main(){
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
    using namespace OI;
    slove();
    return 0;
}
时间: 2024-12-26 03:38:19

[haoi2009]求回文串的相关文章

马拉车,O(n)求回文串

body { font-family: sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10px; padding-bottom: 10px; background-color: white; padding: 30px } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom: 0 !important } a

Palindrome - URAL - 1297(求回文串)

题目大意:RT 分析:后缀数组求回文串,不得不说确实比较麻烦,尤其是再用线段数进行查询,需要注意的细节地方比较多,比赛实用性不高......不过练练手还是可以的. 线段数+后缀数组代码如下: =========================================================================================================================================== #include<stdio

HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列,该子序列分为三部分,第一部分与第三部分相同,第一部分与第二部分对称,如果存在求最长的符合这种条件的序列. 思路:用Manacher算法来处理回文串的长度,记录下以每一个-1(Manacher算法的插入)为中心的最大回文串的长度.然后从最大的开始穷举,只要p[i]-1即能得出以数字为中心的最大回文串的长度,然后找到右边对应的'-1',判断p[i]是不是大于所穷举的长度,如果当前的满足三段,那么就跳出,继续

Codeforces Round #427 (Div. 2) D. Palindromic characteristics(Manacher求回文串)

题目链接:Codeforces Round #427 (Div. 2) D. Palindromic characteristics 题意: 给你一个串,定义k-th回文串,让你求每个k-th的数量. 题解: manacher处理好后做一下dp就行了. 当然也可以直接dp不用manacher. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 cons

HDU 1513 Palindrome 求回文串

这个题是走弯路了,刚开始自己DP出了方程,无限MLE,唉 if(s1[i]==s1[j]) dp[i][j]=dp[i+1][j-1]; else dp[i][j]=min(dp[i][j-1],dp[i+1][j]) +1; 后来百度了一下,这个原来是个经典回文串问题,即先将串置反,然后求LCS........ 然后就是这题卡时间卡的特别厉害,多用了一次strlen就TLE AC: #include<cstdio> #include<string> #include<str

hihocoder 1032 manachar 求回文串O(n)

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <cmath> #include <cstring> #include <stack> #include <set> #include <map> #include <vector> using namespace st

hdu 3294 manacher 求回文串

感谢: http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ O(n)求给定字符串的以每个位置为中心的回文串长度. 中心思想:每次计算位置i的答案时,利用已经算出的1~i-1位置的答案. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define maxn 222222 5 using namespace std; 6 7

求回文串个数

先整理各路大神的题解 Orz,以后再埋坑 SP7586 NUMOFPAL - Number of Palindromes Description 求一个串中包含几个回文串. Input 输入一个字符串S Output 包含的回文串的个数. 思路一: 用马拉车求出预处理后以每个字母处的回文半径P[i],遍历一遍,ans=ans+P[i]/2,最终ans就是答案 答案是以每一位为中心的回文串长度/2的和,(如果添加字符则为回文半径长度/2.) 不能理解的话,可以看下这个 # a # a # b #

poj3376 KMP+字典树求回文串数量(n*n)

Finding Palindromes Time Limit: 10000MS   Memory Limit: 262144K Total Submissions: 4043   Accepted: 746 Case Time Limit: 2000MS Description A word is called a palindrome if we read from right to left is as same as we read from left to right. For exam