【Codeforces 486C】Palindrome Transformation
【链接】 我是链接,点我呀:)
【题意】
【题解】
首先把字符串分成两个部分 1..n/2 和 n/2+1..n这两个部分 (如果n是奇数比较特殊,右半部分是n/2+2..n) 然后如果p落在右半部分那个区间的话 就让它做一下对称 到左半部分来 因为不可能从右边那个区间移动到左边那个区间的(跨越n到达1),那样做太不划算 这两个区间其实是等价的,因为转换的代价都是相同的 只需让光标在一个区间里面移动就好 然后我们就只要考虑一个区间了(1..n/2), 先算出来每个位置转换成回文串对应的位置的字符需要的代价cost[i] 然后求一个前缀和(我直接在cost[i]上求的前缀和,直接导致我忘记cost[i]代表的是cost[1..i]。。。。) 然后再把这一个区间分成(1..p-1)和(p+1,n/2) 我们用前缀和求出cost[1..p-1]和cost[p+1,n/2] 这一部分答案是肯定要累加的。 然后我们只要知道我们往左和往右走最近需要走到哪里(因为不一定非得走到1或者走到n/2) 记往左走最少需要走的步数为leftstep,同理向右为rightstep (如果不用往左走或不用往右走那么对于的xxxstep=0) 那边要的步数少,我们就先走到那边 因为这样的话,回到p位置所需要的花费比较少 则答案累加min(leftstep,rightstep)*2+max(leftstep,rightstep) 这样就做完了!【代码】
import java.io.*;
import java.util.*;
public class Main {
static InputReader in;
static PrintWriter out;
public static void main(String[] args) throws IOException{
//InputStream ins = new FileInputStream("E:\\rush.txt");
InputStream ins = System.in;
in = new InputReader(ins);
out = new PrintWriter(System.out);
//code start from here
new Task().solve(in, out);
out.close();
}
static int N = 50000;
static class Task{
final int N = (int)1e5;
String s;
int n,p;
int cost[];
int get_sum(int l,int r) {
if (l>r) return 0;
return cost[r]-cost[l-1];
}
public void solve(InputReader in,PrintWriter out) {
cost = new int[N+10];
n = in.nextInt();p = in.nextInt();
s = in.next();
StringBuilder sb = new StringBuilder(s);
sb.insert(0, ' ');
s = sb.toString();
int half = n/2;
for (int i = 1;i <= half;i++) {
int j = n-i+1;
int x = s.charAt(i)-'a'+1;
int y = s.charAt(j)-'a'+1;
int temp1 = Math.abs(x-y);
int temp2 = 26-Math.max(x, y) + Math.min(x, y) - 1 + 1;
cost[i] = Math.min(temp1, temp2);
}
for (int i = 1;i <= half;i++) cost[i]+=cost[i-1];
if (cost[half]==0) {
out.println(0);
return;
}
int ans = 0;
if (n%2==1 && p==half+1) {
ans++;
p--;
}
if (p>half) {
int delta;
if (n%2==1) {
delta = p-(half+1);
p = half+1-delta;
}else {
delta = p-half;
p = half-delta+1;
}
}
ans = ans + get_sum(p,p);
int leftcost = get_sum(1,p-1);
int rightcost = get_sum(p+1,half);
ans = ans + leftcost + rightcost;
int leftstep = 0,rightstep = 0;
int temp = 0;
for (int i = p-1;i >= 1;i--) {
if (temp==leftcost) break;
leftstep++;
temp+=get_sum(i,i);
}
temp = 0;
for (int i = p+1;i <= half;i++) {
if (temp==rightcost) break;
rightstep++;
temp+=get_sum(i,i);
}
//out.println("leftstep="+leftstep+" rightstep="+rightstep);
//out.println("leftcost="+leftcost+" rightcost="+rightcost);
//out.println("ans="+ans);
int mi = Math.min(leftstep, rightstep);
int ma = Math.max(leftstep, rightstep);
ans = ans + mi*2 + ma;
out.println(ans);
}
}
static class InputReader{
public BufferedReader br;
public StringTokenizer tokenizer;
public InputReader(InputStream ins) {
br = new BufferedReader(new InputStreamReader(ins));
tokenizer = null;
}
public String next(){
while (tokenizer==null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(br.readLine());
}catch(IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
}
}