zoukankan      html  css  js  c++  java
  • HihoCoder

    Sample Input

    3
    9
    8 7 5 1 9 2 6 4 3
    1 2 3 4 5 6 7 8 9
    9
    8 7 5 1 9 2 6 4 3
    1 2 5 4 3 6 7 8 9
    9
    8 7 5 1 9 2 6 4 3
    1 2 5 6 4 3 7 8 9

    Sample Output

    Case #1: 6
    Case #2: 4
    Case #3: -1

    Prof.Q is a sophisticated professor who has insights into quadrillions of sorting algorithms, especially into bubble sort. Bubble sort is a simple algorithm that repeatedly steps through the array to be sorted, compares each pair of adjacent elements and swaps them if they are in the wrong order. In brief, bubble sort executes the following iteration over and over again until the array is sorted.


    This is your first day becoming a student of Prof.Q, so he gives you two arrays A[1..N] and B[1..N] of length N as a placement test. Your task is to check whether it is possible to execute the aforementioned iteration several times on the array A and then transform it into the array B. Furthermore, determine the minimum times of iteration to achieve it if it is possible.

    Input

    The first line contains one integer T, indicating the number of test cases.

    The following lines describe all the test cases. For each test case:

    The first line contains one integer N.

    The second line contains N integers A[1], A[2], · · · , A[N].

    The third line contains N integers B[1], B[2], · · · , B[N].

    1 ≤ T ≤ 1000, 1 ≤ N ≤ 105 , 1 ≤ ai ≤ 109 (i = 1, 2, · · · , N).

    It is guaranteed that the sum of N in all the test cases does not exceed 106.

    Output

    For each test case, print "Case #x: y" (without quotes) in one line, indicating that this is the x-th test case and the minimum number of iterations for this test case is y if it is possible, print y as −1 otherwise.

    题意:冒泡排序,两个for语句,第一个表示进行了几轮,第二个表示从左往右遍历,如果左边的大于右边的,则交换。现在给定A数组,B数组。  问A数组是否可以根据上述的规则进行K轮排序得到B, 如果可以,求出K,否则输出-1;

    思路:我们不难根据位置的变化得到K; 然后我们可以需要求出A数组进行K轮排序后的数组。  这里根据逆序对+二分来求得。

    因为每一轮排序下来,新的逆序对rev和上一轮的关系是:rev[i]=max(pre[i+1],0);所以我们得到K轮后的结果,和B对比即可。

    (注意这个数组的大小是1e9,我们需要离散化,即根据大小为第一关键字,位置为第二关键字排序。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    int a[maxn],rev[maxn],b[maxn],ans[maxn],pos[maxn],sum[maxn],N;
    void add(int x,int v){ for(;x<=N;x+=(-x)&x) sum[x]+=v; }
    int query(int x){int res=0; for(;x;x-=(-x)&x) res+=sum[x]; return res;}
    struct in{int x,pos; }s[maxn];
    bool cmp(in w,in v ){ return w.x==v.x?w.pos<v.pos:w.x<v.x;}
    void fcy(int f[]){
        rep(i,1,N) s[i].x=f[i],s[i].pos=i; sort(s+1,s+N+1,cmp);
        rep(i,1,N) f[s[i].pos]=i;
    }
    int main()
    {
        int T,C=0,K;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&N); K=0;
            rep(i,1,N) scanf("%d",&a[i]);
            rep(i,1,N) scanf("%d",&b[i]);
            fcy(a); fcy(b); //离散化
            rep(i,1,N) pos[a[i]]=i;
            rep(i,1,N) K=max(K,pos[b[i]]-i); //求K
            rep(i,1,N) rev[i]=sum[i]=0;
            rep(i,1,N) {
               rev[i]=i-1-query(a[i]);
               add(a[i],1);
            }//求A数组的逆序对
            rep(i,1,N) rev[i]=max(0,i+K>N?0:rev[i+K]-K);
            rep(i,1,N) sum[i]=0;
            rep(i,1,N) add(i,1);
            for(int i=N;i>=1;i--){
                int L=1,R=N,res;
                while(L<=R){
                    int Mid=(L+R)>>1;
                    if(query(Mid)>=i-rev[i]) res=Mid,R=Mid-1;
                    else L=Mid+1;
                } ans[i]=res; add(res,-1);
            }//二分定位答案
            rep(i,1,N) if(ans[i]!=b[i]) {K=-1; break;}
            printf("Case #%d: %d
    ",++C,K);
        }
        return 0;
    }
  • 相关阅读:
    jQuery对select操作
    左眼跳跳 100万
    [推荐] 世界上最健康的作息时间表
    放弃了mapbar 选用google map
    记录
    WPF等待窗口
    PL界面
    C# 获得随机数
    组合
    delphi版淘小宝图片下载工具
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10221838.html
Copyright © 2011-2022 走看看