zoukankan      html  css  js  c++  java
  • [NOIP2013]火柴排队

    【题目描述】

    思路{
      首先贪心地想,应该是小怼小,大怼大。即A(i)<=A(i+1),B(i)<=B(i+1),这是排序不等式
      证明它,我们需要使用和式恒等变换(感谢朱峰昊(朱哥)的大力支持){
        设A(i)<=A(i+1),B(i)<=B(i+1),证明:
          ∑A(i)*B(i)(顺序和)
          >=∑A(i)*B( j(i) )(乱序和)
          >=∑A(i)*B(n-i+1)(逆序和)
          其中j(i)为一个任意的对应关系。
          设S[i]=∑B(k)(k<=i),S'[i]=∑B(  j(k) );易知,S[i]<=S‘[i];又因为A(i)<=A(i+1)
          所以S[i]*(A[i+1]-A[i])>=S’[i]*(A[i+1]-A[i])
          ∑A(i)*B(i)=∑S[i]*(A[i+1]-A[i])(i<=n-1)+A[n]*B[n]
                       >=∑S‘[i]*(A[i+1]-A[i])(i<=n-1)+A[n]*B[n]
                       =∑A(i)*B( j(i) );
                                 同理证得右边也成立,问题得证。
              }
      问题解的min为∑(A[i]-B[i])^2=∑A[i]^2+∑B[i]^2-2∑A(i)*B(i).
      前两项是恒定的,故后一项取最大即可,即为顺序和。
            可以统计出每个位置当前点所对应的下标pos[i]。首状态是位置依次递增的。
            而末状态为pos[i],pos[i+1]......pos[n];
            要统计多少步,不妨反过来考虑。
            由于交换两个数只改变这两个数所成的逆序对。
            反过来考虑,就是把一个存在逆序对的数组变成一个非严格上升的子序列,
            且每次交换操作只改变一对。
            那么,只需要用树状数组统计pos下标的逆序对就可以了。

    }

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<queue>
     7 #include<ctime>
     8 #include<cmath>
     9 #include<list>
    10 #include<deque>
    11 #include<stack>
    12 #include<map>
    13 #include<set>
    14 #define RG register
    15 #define LL long long
    16 #define dd double
    17 #define maxx 200001
    18 #define rs (o*2+1)
    19 #define ls (o*2)
    20 #define mid ((L+R)/2)
    21 #define MOD 99999997
    22 #define low(k) (k)&(-k)
    23 using namespace std;
    24 LL n;LL ans;
    25 struct matrix{
    26 LL num,pos;
    27   matrix () {}
    28   matrix(int nn,int pp):num(nn),pos(pp) {}
    29 };
    30 bool comp(const matrix & a,const matrix & b){return a.num<b.num;}
    31 bool comp1(const matrix & a,const matrix & b){return a.pos<b.pos;}
    32 matrix a[maxx],b[maxx];LL t[maxx];int tree[maxx];
    33 void Insert(LL p){for(RG LL i=p;i<=n;i+=low(i))tree[i]++;}
    34 LL ask(LL p){LL sum=0;for(RG int i=p;i;i-=low(i))sum+=tree[i];return sum;}
    35 int main(){
    36   freopen("MatchNOIP2013.in","r",stdin);
    37   freopen("MatchNOIP2013.out","w",stdout);
    38   scanf("%lld",&n);LL x;
    39   for(RG int i=1;i<=n;++i)scanf("%lld",&x),a[i]=matrix(x,i);
    40   for(RG int i=1;i<=n;++i)scanf("%lld",&x),b[i]=matrix(x,i);
    41   sort(a+1,a+n+1,comp);sort(b+1,b+n+1,comp);
    42   for(RG int i=1;i<=n;++i)t[a[i].pos]=b[i].pos;
    43   for(RG int i=1;i<=n;++i){
    44     Insert(t[i]);
    45     ans+=(i-ask(t[i])+MOD)%MOD;
    46     ans%=MOD;
    47   }
    48   printf("%lld",ans);return 0;
    49 }
  • 相关阅读:
    YUI3学习笔记 ( 3 )
    DataSnap基础
    SQL语句的添加、删除、修改多种方法
    用命令实现Win7远程桌面关机和重启
    Delphi笔记数据库开发
    Delphi数据库处理
    数据库左连接的一点知识
    FastReport4.6程序员手册_翻译
    ADO BUG之'无法为更新定位行....' 解决之道
    动态将ADOQuery数据移植到ClientDataSet通用函数
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6898454.html
Copyright © 2011-2022 走看看