P5041 HAOI2009 求回文串

2022-10-09 02:42:13 字數 1862 閱讀 8830

所謂回文串,就是對於給定的字串,正著讀和反著讀都一樣,比如abcba就是乙個回文串,abcab則不是。我們的目標是對於任意輸入的字串,不斷將第i個字元和第i+1個字元交換,使得該串最終變為回文串。求最少交換次數。

乙個由大寫字母字母組成的字串。

若能經過有限次操作能將原串變為回文串,則輸出最少操作次數;否則輸出-1。

輸入輸出樣例

輸入

shllzshzs
輸出
4
說明/提示

樣例說明

交換 l 和 z 變成 shlzlshzs

交換 l 和 z 變成 shzllshzs

交換 l 和 s 變成 shzlslhzs

交換 h 和 z 變成 shzlslzhs

資料範圍

\(40\%\) 的資料, 長度\(\leq50000\)

\(100\%\) 的資料, 長度\(\leq10^6\)

貪心,逆序對

貪心策略:每次選擇最靠外邊的字元作為回文串的一部分

證明(摘自 tsreaper ):

構造回文串的過程,實際上是每次選擇一對字母並把它們交換到字串頭尾的過程。考慮字母 \(x\) 和字母 \(y\) 哪 個先選,分以下情況討論:

// %%%skyqwq

#include //#define int long long

#define help

#define pb push_back

#define fi first

#define se second

#define mkp make_pair

using namespace std;

typedef long long ll;

typedef pairpii;

typedef pairpll;

template bool chkmax(t &x, t y)

template bool chkmin(t &x, t y)

template void inline read(t &x)

while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();

x *= f;

}const int n=1e6+5;

string s;

int n,res[n],b[n],c[n];

vectora[26];

bool v[n];

void add(int x,int y)

int ask(int x)

int main()

int f=0;

for(int i=0;i<26;i++)

if(a[i].size()&1)f++;

if(n%2==0&&f||n%2==1&&f!=1)puts("-1");

else

}int l=1,r=n,pos=1;

while(pos<=n)

if(pos>n||l>r)break;

v[pos]=true;

res[l++]=pos++;

int t=a[b[pos-1]][a[b[pos-1]].size()-1];

v[t]=true;

res[r--]=t;

a[b[pos-1]].pop_back();

} }ll ret=0;

for(int i=n;i;i--)ret+=ask(res[i]),add(res[i],1);

cout

}

洛谷P5041 HAOI2009 求回文串

傳送門 題目描述 所謂回文串,就是對於給定的字串,正著讀和反著讀都一樣,比如abcba就是乙個回文串,abcab則不是。我們的目標是對於任意輸入的字串,不斷將第i個字元和第i 1個字元交換,使得該串最終變為回文串。求最少交換次數。輸入格式 乙個由大寫字母字母組成的字串。輸出格式 若能經過有限次操作能...

haoi2009 求回文串

所謂回文串,就是對於給定的字串,正著讀和反著讀都一樣,比如abcba就是乙個回文串,abcab則不是。我們的目標是對於任意輸入的字串,不斷將第i個字元和第i 1個字元交換,使得該串最終變為回文串。求最少交換次數。題解 有一種做法是貪心 就是每次找到最左端的字元,然後找到這序列中最右邊的一樣的字元,然...

P2513 HAOI2009 逆序對數列

題目描述 對於乙個數列,如果有iaj,那麼我們稱ai與aj為一對逆序對數。若對於任意乙個由1 n自然數組成的數列,可以很容易求出有多少個逆序對數。那麼逆序對數為k的這樣自然數數列到底有多少個?錯誤日誌 沒想対,菜是原罪,最近狀態不佳 在一段 1 i 1 的排列中加入 i 你可以控制 i 插入的位置,...