树状数组 NOIP2013 火柴排队

1438. [NOIP2013]火柴排队

★★★   输入文件:MatchNOIP2013.in   输出文件:MatchNOIP2013.out   简单对比
时间限制:1 s   内存限制:128 MB

【题目描述】

样例一输入:

4

2 3 1 4

3 2 1 4

样例二输入:

4

1 3 4 2

 

这个题似乎在考数学小常识,2333......

首先可以得到两列火柴的距离和为∑a2+∑b2-2*∑ai*bi,显然距离仅∑ai*bi有关

由排序不等式,逆序积之和小于乱序积之和,乱序积之和小于顺序积之和

如果你非要看成均值什么的那就随意了

那么这个题就是要求相对与第一列的逆序对数了,当然可以相对于第二列

 

那么

贴代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int m=99999997;
 8 struct data{
 9     int num,val;
10 }a[100010],b[100010];
11 int n;
12 int loc[100010];
13 int tree[100015];
14 int ans;
15 
16 bool cmp1(const data&aa,const data&bb){
17     return aa.val<bb.val;
18 }
19 
20 bool cmp2(const data&aa,const data&bb){
21     return aa.num<bb.num;
22 }
23 
24 void add(int pos){
25     for(int i=pos;i<=n+5;i+=i&(-i)) tree[i]++;
26 }
27 
28 int ask(int pos){
29     int tot=0;
30     for(int i=pos;i>0;i-=i&(-i)) tot+=tree[i];
31     return tot;
32 }
33 
34 int main(){
35     freopen("MatchNOIP2013.in","r",stdin);
36     freopen("MatchNOIP2013.out","w",stdout); 
37     scanf("%d",&n);
38     for(int i=1;i<=n;i++) scanf("%d",&a[i].val),a[i].num=i;
39     for(int i=1;i<=n;i++) scanf("%d",&b[i].val),b[i].num=i;
40     sort(a+1,a+n+1,cmp1);
41     sort(b+1,b+n+1,cmp1);
42     for(int i=1;i<=n;i++) loc[a[i].num]=b[i].num;
43     sort(a+1,a+n+1,cmp2);
44     for(int i=1;i<=n;i++){
45         add(loc[i]);
46         ans=ans+i-ask(loc[i]);
47         ans=ans%m;
48     }
49     printf("%d\n",ans%m);
50     fclose(stdin);
51     fclose(stdout);
52     return 0;
53 }

 

posted @ 2017-04-27 01:38  zwube  阅读(248)  评论(0编辑  收藏  举报