Codeforces Round 930 (Div. 2) --- D. Pinball --- 题解

目录

D. Pinball:

题目大意:

思路解析:

代码实现:

代码一:

代码二:


D. Pinball:

题目大意:

思路解析:

 假设字符串为 >>><<<, 当前位置为第四位, 那我们可以想到我们如果处在 < 这个位置上,那我们应该找到左边第一个 > 位置,位移到了>位置后,我们应该找到右边第一个 <位置,每次经过的点 > 会改变为 <,  > 会改变为 <,如果这样修改肯定是复杂的,我们可以利用双指针来寻找,这样就可以省略中间将 > 修改为 < 和 < 修改为 > 的过程,但是如果出现字符串形如 <><><><>这样的双指针每次只能移动个位置,然后时间复杂度任然会退化为O(N*N)的时间复杂度。 (参考代码一)

那我们可以发现上诉的分析过程中,我们每次只需要找到<>这两个位置,那我们想到是否可以利用前缀和来求解。

假设字符串为 ><<>><,现在处于 i == 4的位置, 那么答案为 (6 - 4) + (6 - 1) + (7 - 1) 等价于 2 * (6 - 4 - 1) + 4 + (6 + 1),我们可以发现 6 是一个前缀和,(4+1)也是一个前缀和,貌似看作为前缀和很合理,然后再结合第一个思想和举几个例子验证,发现确实可以利用前缀和假设 (参考代码二)

代码实现:

代码一:

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int inf = (int) 2e7;
    public static void main(String[] args) throws IOException {

        int t = f.nextInt();
        while (t > 0) {
            solve();
            w.println();
            t--;
        }

        w.flush();
        w.close();
        br.close();
    }

    static int maxN = (int) 1e6 + 5;
    static int N = (int) 1e6;
    public static void solve() {
        int n = f.nextInt();
        char[] s = (" " + f.next()).toCharArray();
        int[][] l = new int[n+2][2];
        int[][] r = new int[n+2][2];
        r[n+1][0] = n + 1; r[n+1][1] = n+1;
        for (int i = 1; i <= n; i++) {
            if (s[i] == '>'){
                l[i][0] = i;
                l[i][1] = l[i-1][1];
            }else {
                l[i][1] = i;
                l[i][0] = l[i-1][0];
            }
        }
        for (int i = n; i >= 1; i--) {
            if (s[i] == '>'){
                r[i][0] = i;
                r[i][1] = r[i+1][1];
            }else {
                r[i][1] = i;
                r[i][0] = r[i+1][0];
            }
        }

        // 0 >   1 <
        for (int i = 1; i <= n; i++) {
            int p = i, q = i;
            int op = 0;
            int ned = 0;
            if (s[i] == '>'){
                op = 1;
                ned = 1;
            }
            long ans = 0;
            while (!(p == 0 || q == n + 1)){
                if (op == 1){
                    if (q == r[q][ned]) q++;
                    q = r[q][ned];
                    ans += q - p;
                    ned ^= 1;
                    op = 0;
                }else {
                    if (p == l[p][ned]) p--;
                    p = l[p][ned];
                    ans += q-p;
                    ned ^= 1;
                    op = 1;
                }
            }
            w.print(ans + " ");
        }
    }




    public static class Node{
        int l,r;
        int[] sum = new int[2];

    }

    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextLine() {
            String str = null;
            try {
                str = reader.readLine();
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            return str;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public Double nextDouble() {
            return Double.parseDouble(next());
        }

        public BigInteger nextBigInteger() {
            return new BigInteger(next());
        }
    }
}

代码二:

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int inf = (int) 2e7;
    public static void main(String[] args) throws IOException {

        int t = f.nextInt();
        while (t > 0) {
            solve();
            w.println();
            t--;
        }

        w.flush();
        w.close();
        br.close();
    }

    static int maxN = (int) 1e6 + 5;
    static int N = (int) 1e6;
    static int[] cntR;
    static int[] cntL;
    static long[] sumR;
    static long[] sumL;
    static int n;
    public static void solve() {
        n = f.nextInt();
        char[] s = (" " + f.next()).toCharArray();
        cntL = new int[n+1];
        cntR = new int[n+1];
        sumL = new long[n+1];
        sumR = new long[n+1];
        for (int i = 1; i <= n; i++) {
            cntL[i] = cntL[i - 1];
            cntR[i] = cntR[i - 1];
            sumL[i] = sumL[i - 1];
            sumR[i] = sumR[i - 1];
            if (s[i] == '>'){
                cntR[i]++;
                sumR[i] += i;
            }else {
                cntL[i]++;
                sumL[i] += i;
            }
        }
        for (int i = 1; i <= n; i++) {
            if (s[i] == '>'){
                if (cntR[i] > cntL[n] - cntL[i]){
                    int p = getpre(cntR[i] - (cntL[n] - cntL[i]));
                    w.print(2 * ((sumL[n] - sumL[i]) - (sumR[i] - sumR[p-1])) + n + i + 1);
                    w.print(" ");
                }else {
                    int p = getsuf((cntL[n] - cntL[i]) - cntR[i]);
                    w.print(2 * ((sumL[p] - sumL[i-1]) - sumR[i]) + i);
                    w.print(" ");
                }
            }else {
                if (cntL[n] - cntL[i-1] > cntR[i]){
                    int p = getsuf((cntL[n] - cntL[i-1]) - cntR[i] - 1);
                    w.print(2 * ((sumL[p] - sumL[i-1]) - sumR[i]) - i);
                    w.print(" ");
                }else {
                    int p = getpre(cntR[i] - (cntL[n] - cntL[i-1]) + 1);
                    w.print(2 * ((sumL[n] - sumL[i - 1]) - (sumR[i] - sumR[p - 1])) + (n+1) - i);
                    w.print(" ");
                }
            }
        }
    }

    public static int getpre(int x){
        int l = 1, r = n;
        int res = 0;
        while (l <= r){
            int m = (l + r) >> 1;
            if (cntR[m] >= x){
                r = m - 1;
                res = m;
            }else {
                l = m + 1;

            }
        }
        return res;
    }

    public static int getsuf(int x){
        int l = 1, r = n;
        int res = 0;
        while (l <= r){
            int m = (l + r) >> 1;
            if (cntL[n] - cntL[m] <= x){
                res = m;
                r = m - 1;
            }else {
                l = m + 1;
            }
        }
        return res;
    }

    public static class Node{
        int l,r;
        int[] sum = new int[2];

    }

    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextLine() {
            String str = null;
            try {
                str = reader.readLine();
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            return str;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public Double nextDouble() {
            return Double.parseDouble(next());
        }

        public BigInteger nextBigInteger() {
            return new BigInteger(next());
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Studying~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值