Codeforces Global Round 23 C. Permutation Operations

赛时随便写了个做法,看standing,发现很多人的做法也是很奇特
赛后看了官方题解。。翻译下

题意:

每次可以给一个任意的后缀里的所有数 + i +i +i
执行n次。
使得逆序对最少。

思路:

tip1:

什么时候逆序对最少?
序列非递减。

解法:

处理出差分数组
d = [ a 2 − a 1 , a 3 − a 2 , . . . , a n − a n − 1 ] d = [a_2-a_1,a_3-a_2,...,a_n-a_{n-1}] d=[a2a1,a3a2,...,anan1]

那么什么时候序列非递减?转换为差分数组都是非负。

d i = a i + 1 − a i , i ∈ [ 1 , n − 1 ] d_i = a_{i+1}-a_{i} ,i\in[1,n-1] di=ai+1ai,i[1,n1]
显然 d i ≥ − a i d_i \ge -a_i diai
那么我们可以对位置 i + 1 i+1 i+1开始的后缀 + a i +a_i +ai.
由于每个 a i a_i ai都是唯一的,所以可以构造出非递减序列。

最后输出的时候,注意 i = n i=n i=n时,就另 a n s [ a [ i ] ] = n ans[a[i]] = n ans[a[i]]=n即可。

AC(Java)

package com.hgs.codeforces.contest.globalround.contest23.c2;

/**
 * @author youtsuha
 * @version 1.0
 * Create by 2022/10/16 14:13
 */
import java.util.*;
import java.io.*;
public class Main {
    static FastScanner cin;
    static PrintWriter cout;

    private static void init()throws IOException {
        cin = new FastScanner(System.in);
        cout = new PrintWriter(System.out);
    }

    private static void close(){
        cout.close();
    }
    private static void sol()throws IOException {
        int n = cin.nextInt();
        int a[] = new int[n];
        for(int i = 0; i < n; i ++ ) {
            int p = cin.nextInt();
            p--;
            a[p] = (i + 1) + 1;
        }
        for(int i = 0; i < n; i ++ ) cout.print(Math.min(a[i],n) + " ");
        cout.println();
    }
    public static void main(String[] args) throws IOException {
        init();
        int tt = cin.nextInt();
        while(tt -- > 0)sol();
        close();
    }
}
class FastScanner {
    BufferedReader br;
    StringTokenizer st = new StringTokenizer("");

    public FastScanner(InputStream s) {
        br = new BufferedReader(new InputStreamReader(s));
    }

    public FastScanner(String s) throws FileNotFoundException {
        br = new BufferedReader(new FileReader(new File(s)));
    }

    public String next() throws IOException {
        while (!st.hasMoreTokens()){
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) { e.printStackTrace(); }
        }
        return st.nextToken();
    }

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值