zoukankan      html  css  js  c++  java
  • 【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());
            }
        }
    }
    
  • 相关阅读:
    《程序员代码面试指南》第八章 数组和矩阵问题 数组排序之后相邻数的最大差值
    《程序员代码面试指南》第八章 数组和矩阵问题 数组中未出现的最小正整数
    《程序员代码面试指南》第八章 数组和矩阵问题 数组的partition 调整
    《程序员代码面试指南》第八章 数组和矩阵问题 不包含本位置值的累乘数组
    《程序员代码面试指南》第八章 数组和矩阵问题 打印N 个数组整体最大的Top K
    《程序员代码面试指南》第八章 数组和矩阵问题 数组中子数组的最大累乘积
    《程序员代码面试指南》第八章 数组和矩阵问题 在数组中找到一个局部最小的位置
    《程序员代码面试指南》第八章 数组和矩阵问题 子矩阵的最大累加和问题
    MySQL 进阶4 SQL常见函数: 字符函数/数学函数/日期函数/流程控制函数(if/case)
    MySQL 进阶3 排序查询
  • 原文地址:https://www.cnblogs.com/AWCXV/p/10427543.html
Copyright © 2011-2022 走看看