牛客周赛round34 G小红的元素交换 --- 题解(置换环)

目录

G小红的元素交换:

题目大意: 

思路解析:

代码实现:


G小红的元素交换:

题目大意: 

思路解析:

        我们让 i - a[i] 两个元素之间连一条边,那么 1 3 2 4 =在不考虑颜色的情况下,可以变为两个环 (1)(3 2 4),最少交换次数为2。可以发现在任意环下,如果要将环内元素变为有序的,至少需要cnt - 1次操作,cnt是环内元素的个数。

        但是本题有另一个要求,即不同的颜色的元素之间才能交换,如果一个环中元素为1或者(一个环中元素大于1并且环中两个颜色的元素都有)那么这样的环1都能让其变为有序。

        那么我们只需要判断哪些环是只有一个颜色的,我们将这样纯色的环,通过一次交换,让其变为混色的即可。

代码实现:

        

import java.io.*;
import java.util.*;


public class Main {
    static long mod = (int) 1e9 + 7;
    static int base = 131;
    static long[] pow = new long[1000005];
    static char[] s;
    static int MAXN = 1000005;


    public static void main(String[] args) throws IOException {
        FastScanner f = new FastScanner();
        PrintWriter w = new PrintWriter(System.out);
        int n = f.nextInt();
        int[] a = new int[n+1];
        for (int i = 1; i <= n; i++) {
            a[i] = f.nextInt();
        }
        String str = " " + f.nextString();
        char[] s = str.toCharArray();

        int[] vis = new int[n+1];
        PriorityQueue<Integer> vh = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        PriorityQueue<Integer> vr = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        PriorityQueue<Integer> vw = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        for (int i = 1; i <= n; i++) {
            int[] tong = new int[26];
            int pre = i;
            int cnt = 0;
            while (vis[pre] == 0){
                tong[s[pre] - 'A']++;
                vis[pre]++;
                pre = a[i];
                cnt ++;
            }
            if (tong['W' - 'A'] > 0 && tong['R' - 'A'] > 0){
                vh.add(cnt);
            } else if (tong['W' - 'A'] > 0) {
                vw.add(cnt);
            }else if (tong['R' - 'A'] > 0){
                vr.add(cnt);
            }
        }
        int res = 0;
        while(!vr.isEmpty() && !vw.isEmpty() && (vr.peek() > 1 || vw.peek() > 1)){
            int x = vr.poll();
            int y = vw.poll();
            res++;
            vh.add(x + y);
        }
        while (!vr.isEmpty() && !vh.isEmpty()){
            int x = vr.poll();
            if (x == 1) break;
            int y = vh.poll();
            res++;
            vh.add(x+y);
        }
        while (!vw.isEmpty() && !vh.isEmpty()){
            int x = vw.poll();
            if (x == 1) break;
            int y = vh.poll();
            res++;
            vh.add(x+y);
        }
        for (Integer integer : vh) {
            res += integer - 1;
        }
        if (!vr.isEmpty() && vh.isEmpty() && vr.peek() > 1) res = -1;
        if (!vw.isEmpty() && vh.isEmpty() && vw.peek() > 1) res = -1;
        w.println(res);
        w.flush();
        w.close();

    }


    private static class FastScanner {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        private FastScanner() throws IOException {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        private short nextShort() throws IOException {
            short ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do ret = (short) (ret * 10 + c - '0');
            while ((c = read()) >= '0' && c <= '9');
            if (neg) return (short) -ret;
            return ret;
        }

        private int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do ret = ret * 10 + c - '0';
            while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do ret = ret * 10 + c - '0';
            while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        private char nextChar() throws IOException {
            byte c = read();
            while (c <= ' ') c = read();
            return (char) c;
        }

        private String nextString() throws IOException {
            StringBuilder ret = new StringBuilder();
            byte c = read();
            while (c <= ' ') c = read();
            do {
                ret.append((char) c);
            } while ((c = read()) > ' ');
            return ret.toString();
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }
    }
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Studying~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值