【Codeforces 486C】Palindrome Transformation

【链接】 我是链接,点我呀:)
【题意】

光标一开始在p的位置 你可以用上下左右四个键位移动光标(左右)或者更改光标所在的字符(上下增加或减少ascill码) 问你最少要操作多少次才能使得字符串变成回文

【题解】

首先把字符串分成两个部分 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());
        }
    }
}
posted @ 2019-02-24 19:41  AWCXV  阅读(185)  评论(0编辑  收藏  举报