• 测试1T1


    题目描述

    Lyk得到了一个1~n的全排列。Txm每次会交换第i个数和第j个数,对于每次交换,lyk需要回答该全排列的逆序对数为多少。
    “1、2、3、4......248289469!”lyk如是回答道。
    “最后答案取模2......”

    输入

    第一行一个数,n
    第二行为1~n的某个全排列
    第三行一个数m,表示交换操作的次数。
    接下来m行,每行两个数i和j

    输出

    M行,表示m次交换后的答案。

    样例输入

    4
    1 2 3 4
    1
    1 2
    

    样例输出

    1

    提示

    Constraints

    对于30%,n,m<=1000

    对于100%,n,m<=100000

    第一次做果断被坑
    归并+暴力线扫忘了a[i]>a[j]时的ans--
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int a[100005],b[100005],A[100005];
    long long ans;
    void merge(int l,int mid,int r)
    {
        int i=l;int j=mid+1;int k=l;
        while(i<=mid&&j<=r)
        {
            if(a[i]<=a[j])
            b[k++]=a[i++];else ans+=mid-i+1,b[k++]=a[j++];
        }
        for (int p=i;p<=mid;p++)
        b[k++]=a[p];
        for (int p=j;p<=r;p++)
        b[k++]=a[p];
        for(int p=l;p<=r;p++)
        a[p]=b[p];
    }
    void merge_sort(int l,int r)
    {
        if(l==r) return;
        int mid=(l+r)/2;
        merge_sort(l,mid);
        merge_sort(mid+1,r);
        merge(l,mid,r);
    }
    
    int main()
    {
        freopen("lyk.in","r",stdin);
        freopen("lyk.out","w",stdout);
        int n,m;
        ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
          scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
          A[i]=a[i];  
        merge_sort(1,n);  
        scanf("%d",&m);
        int x,y;
        long long ANS=ans;
        for(int i=1;i<=m;i++)
        {
            //ans=ANS;
            scanf("%d %d",&x,&y);
            if(x>y) swap(x,y);
            for(int k=x+1;k<=y-1;k++)
            {
                if(A[k]>A[x])ans++;else ans--;
                if(A[k]>A[y])ans--;else ans++;
            }
            if(A[x]<A[y]) ans++;
                    //忘了else ans--;
            swap(A[x],A[y]);
            printf("%lld
    ",ans%2);
        }
        return 0;
    }

    正解:

    每次交换a[i]和a[j]时会对a[i+1..j-1]中的数询问,加上比a[i]大的,减去比a[i]小的;加上比a[j]小的,减去比a[j]大的;最后考虑a[i]和a[j]的大小关系

    设分别有z,z1个,则有

    ans+=z-(j-i+1-z)+z1-(j-i+1-z1);等价于ans+=2*z+2*z-1-2*(j-i+1)

    因为最后询问ans%2 所以改变ans的只有最后一步(考虑a[i]和a[j]的关系)

    最后判断i是否等于j

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int a[100005],b[100005],A[100005];
    long long ans;
    void merge(int l,int mid,int r)
    {
        int i=l;int j=mid+1;int k=l;
        while(i<=mid&&j<=r)
        {
            if(a[i]<=a[j])
            b[k++]=a[i++];else ans+=mid-i+1,b[k++]=a[j++];
        }
        for (int p=i;p<=mid;p++)
        b[k++]=a[p];
        for (int p=j;p<=r;p++)
        b[k++]=a[p];
        for(int p=l;p<=r;p++)
        a[p]=b[p];
    }
    void merge_sort(int l,int r)
    {
        if(l==r) return;
        int mid=(l+r)/2;
        merge_sort(l,mid);
        merge_sort(mid+1,r);
        merge(l,mid,r);
    }
    
    int main()
    {
        //freopen("lyk.in","r",stdin);
        //freopen("lyk.out","w",stdout);
        int n,m;
        ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
          scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
          A[i]=a[i];  
        merge_sort(1,n);  
        ans%=2; 
        scanf("%d",&m);
        int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            if(x!=y)
            ans=1^ans;
            printf("%lld
    ",ans);    
        } 
        return 0;
    }

    还被cout坑了

     

  • 相关阅读:
    C#多线程同步重新梳理
    word打不开,Microsoft Office Word 遇到问题需要关闭。。。总提示进入安全...
    SMTP协议
    【转载】Hadoop集群(第10期)_MySQL关系数据库 天高地厚
    备份与恢复的原理 . 天高地厚
    ubuntu server 使用parted分区 天高地厚
    Flex开发中遇到未整理资源 天高地厚
    Oracle RAC + Data Guard 环境搭建 . 天高地厚
    【转载】oracle事务之oracle读一致性 . 天高地厚
    理解PGA(2)pga_aggregate_target详解 . 天高地厚
  • 原文地址:https://www.cnblogs.com/dancer16/p/6840637.html
Copyright © 2020-2023  润新知