zoukankan      html  css  js  c++  java
  • P1966 火柴排队——逆序对(归并,树状数组)

    P1966 火柴排队

    很好的逆序对板子题;

    求的是(x1-x2)*(x1-x2)的最小值;

    x1*x1+x2*x2-2*x1*x2

    让x1*x2最大即可;

    可以证明将b,c数组排序后,一一对应的状态是最大的;

    ac+bd<ad+bc

    ac-ad<bc-bd

    a*(c-d)<b*(c-d)//c-d<0

    a>b(???)

    逆序对合并时一定要加等号!!要判断q1是否超出mid!!!(爆零体验);

    归并写法

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    const int mo=99999997;
    struct node
    {
        int x,id;
    }b[maxn];
    node c[maxn];
    int n;
    bool cmp(node qw,node we)
    {
        return qw.x<we.x;
    }
    int a[maxn];
    int tmp[maxn];
    int ans;
    void work_sort(int l,int r)
    {
        if(l==r) return ;
        int mid=(l+r)>>1;
        work_sort(l,mid);
        work_sort(mid+1,r);
        int q1=l,q2=mid+1;
        for(int i=l;i<=r;i++)
        {
            if((a[q1]<=a[q2]&&q1<=mid)||q2>r)
            {
                tmp[i]=a[q1++];
            }
            else 
            {
                ans+=mid-q1+1;
                ans%=mo;
                tmp[i]=a[q2++];
            }
        }
        for(int i=l;i<=r;i++) a[i]=tmp[i];
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {scanf("%d",&b[i].x);b[i].id=i;}
        for(int i=1;i<=n;i++) {scanf("%d",&c[i].x);c[i].id=i;}
        sort(b+1,b+n+1,cmp);
        sort(c+1,c+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            a[b[i].id]=c[i].id;
        }
        work_sort(1,n);
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    树状数组写法

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    const int mo=99999997;
    struct node
    {
        int x,id;
    }a[maxn];
    node c[maxn];
    int n;
    int d[maxn];
    bool cmp(node qw,node we)
    {
        return qw.x<we.x;
    }
    int b[maxn];
    void add(int x,int y)
    {
        for(;x<=n;x+=x&(-x)) b[x]=(b[x]+y)%mo;
    }
    
    int query(int x)
    {
        int sum=0;
        for(;x;x-=x&(-x)) sum=(sum+b[x])%mo;
        return sum;
    }
    int ans;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {scanf("%d",&a[i].x);a[i].id=i;}
        for(int i=1;i<=n;i++) {scanf("%d",&c[i].x);c[i].id=i;}
        sort(a+1,a+n+1,cmp);
        sort(c+1,c+n+1,cmp);
        for(int i=1;i<=n;i++) d[a[i].id]=c[i].id;
        for(int i=1;i<=n;i++)
        {
            add(d[i],1);
            ans+=i-query(d[i]);
            ans%=mo;
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    实参和形参
    location对象
    区别 apply,call
    窗体之间的交互(window.opener)
    我的升级脚本总结
    Create elements
    history 对象
    函数参数的属性:callee
    发布app store流程
    【转】如何生成静态页面的五种方案
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11650737.html
Copyright © 2011-2022 走看看