SGU 325 Palindrome(贪心)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=325

题意:给出一个字符串。每次可以交换相邻的两个字母。问最少需要多少次可以使得串变为回文串?

思路:从左向右扫描。对于每一个字符,找到其对应的字母,将其移到右侧相应的位置。设此时长度为len(每次移动完后长度会减去2),前面已经移动了num个,当前要移动的位置为k,[num+1,k-1]区间内已经移动走的位x个,则本次需要移动len-(k-num-x)。那么num是可以直接记录的,x是需要计算的。用树状数组。

 

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

#include <cmath>

#include <vector>

#include <queue>

#include <set>

#include <stack>

#include <string>

#include <map>





#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>=0?(x):-(x))

#define i64 long long

#define u32 unsigned int

#define u64 unsigned long long

#define clr(x,y) memset(x,y,sizeof(x))

#define CLR(x) x.clear()

#define ph(x) push(x)

#define pb(x) push_back(x)

#define Len(x) x.length()

#define SZ(x) x.size()

#define PI acos(-1.0)

#define sqr(x) ((x)*(x))

#define MP(x,y) make_pair(x,y)



#define FOR0(i,x) for(i=0;i<x;i++)

#define FOR1(i,x) for(i=1;i<=x;i++)

#define FOR(i,a,b) for(i=a;i<=b;i++)

#define DOW0(i,x) for(i=x;i>=0;i--)

#define DOW1(i,x) for(i=x;i>=1;i--)

#define DOW(i,a,b) for(i=a;i>=b;i--)

using namespace std;





void RD(int &x){scanf("%d",&x);}

void RD(i64 &x){scanf("%I64d",&x);}

void RD(u32 &x){scanf("%u",&x);}

void RD(double &x){scanf("%lf",&x);}

void RD(int &x,int &y){scanf("%d%d",&x,&y);}

void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}

void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}

void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}

void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}

void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}

void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}

void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}

void RD(char &x){x=getchar();}

void RD(char *s){scanf("%s",s);}

void RD(string &s){cin>>s;}





void PR(int x) {printf("%d\n",x);}

void PR(i64 x) {printf("%I64d\n",x);}

void PR(u32 x) {printf("%u\n",x);}

void PR(double x) {printf("%.6lf\n",x);}

void PR(char x) {printf("%c\n",x);}

void PR(char *x) {printf("%s\n",x);}

void PR(string x) {cout<<x<<endl;}



const int N=1000005;

int a[26],n,s[N],last[26],p[N],visit[N];

char str[N];





void add(int x)

{

    while(x<N) s[x]++,x+=x&-x;

}



int get(int x)

{

    int ans=0;

    while(x) ans+=s[x],x-=x&-x;

    return ans;

}



int main()

{

    scanf("%s",str+1);

    n=strlen(str+1);

    int i,k,t;

    FOR1(i,n)

    {

        k=str[i]-'A';

        a[k]++;

        p[i]=last[k];

        last[k]=i;

    }

    k=0;

    FOR0(i,26) k+=(a[i]&1);

    if(k>n%2) return puts("-1"),0;

    i64 ans=0,len=n,preNum=0;

    FOR1(i,n) if(!visit[i])

    {

        t=str[i]-'A';

        k=last[t];

        if(i>=k)

        {

            len--;

            ans+=len/2;

        }

        else

        {

            ans+=len-(k-preNum-get(k));

            visit[k]=1;

            add(k);

            len-=2;

            last[t]=p[k];

        }

        preNum++;

    }

    PR(ans);

    return 0;

}

  

你可能感兴趣的:(ROM)