水题 逆序对 NOIP 2013 火柴排队

题目如下

题目描述 Description

涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

输入描述
Input Description

共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

输出描述
Output Description

输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。

样例输入
Sample Input

[Sample 1]
4
2 3 1 4
3 2 1 4
[Sample 2]
4
1 3 4 2
1 7 2 4

样例输出
Sample Output

[Sample 1]
1
[Sample 2]
2

数据范围及提示 Data Size & Hint

【样例1说明】
最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。
【样例2说明】
最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。
【数据范围】
对于 10%的数据, 1 ≤ n ≤ 10;
对于 30%的数据,1 ≤ n ≤ 100;
对于 60%的数据,1 ≤ n ≤ 1,000;
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ 2^31 - 1。

这个题很水,只是有时候想着想着就脑抽了,毕竟不断的在数组之间转换,很头疼。

不说了,上代码,自己理解去吧。。。。。。。

提示:用第一组为顺序求第二组的逆序对。

代码(别忘了取模):

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define maxn 100500
 5 #define mo 99999997
 6 using namespace std;
 7 int a[maxn],b[maxn],c[maxn],d[maxn],pos[maxn];
 8 int n;
 9 int tree[maxn];
10 int lowbit(int x)
11 {
12     return x&(-x);
13 }
14 void add(int x)
15 {
16     for(int i=x;i<=n;i+=lowbit(i))
17     {
18         tree[i]++;
19         tree[i]%=mo;
20     }
21 }
22 long long sum(int x)
23 {
24     long long ans=0;
25     for(int i=x;i>0;i-=lowbit(i))
26     {
27         ans+=tree[i];
28         ans%=mo;
29     }
30     return ans%mo;
31 }
32 bool cmp(int x,int y)
33 {
34     return a[x]<a[y];
35 }
36 bool cmp1(int x,int y)
37 {
38     return b[x]<b[y];
39 }
40 int main(void)//RP++;
41 {
42     cin>>n;
43     for(int i=1;i<=n;i++)
44     {
45         scanf("%d",&a[i]);
46         c[i]=i;
47     }
48     for(int i=1;i<=n;i++)
49     {
50         scanf("%d",&b[i]);
51         d[i]=i;
52     }
53     sort(c+1,c+n+1,cmp);
54     sort(d+1,d+1+n,cmp1);
55     for(int i=1;i<=n;i++)
56     {
57         a[c[i]]=i;
58         b[d[i]]=i;
59     }//到此为止:排序离散化
60
61     for(int i=1;i<=n;i++)
62     {
63         pos[a[i]]=i;
64     }
65     for(int i=1;i<=n;i++)
66     {
67         b[i]=pos[b[i]];
68     }
69     long long cnt=0;
70     for(int i=n;i>=1;i--)
71     {
72         cnt+=sum(b[i]);
73         cnt%=mo;
74         add(b[i]);
75     }
76     cout<<cnt<<endl;
77     return 0;
78 }

火柴排序.cpp

时间: 2024-10-11 07:49:50

水题 逆序对 NOIP 2013 火柴排队的相关文章

NOIP 2013 火柴排队 程序

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 100000 + 1; 4 const int MOD = 99999997; 5 int n, F[MAXN], C[MAXN]; 6 struct node 7 { 8 int N, H; 9 }Match1[MAXN], Match2[MAXN]; 10 void Update(int x) 11 { 12 for (int i = x; i <

NOIP 提高组2013 火柴排队 (Vijos P1842)

描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ i=1 n (a i ?b i ) 2  ,其中 a i   表示第一列火柴中第 i 个火柴的高度,b i   表示第二列火柴中第 i 个火柴的高度. 每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小.请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模

noip提高组2013 火柴排队

题目链接:https://www.luogu.org/problem/show?pid=1966 这个题啊,naive(虽然我不会证明). 举了个特例,得出结论:对于两列数,一定是最大与最大的相对,最小的与最小的相对. 然后就以离散化一下,然后随便用个树状数组求个逆序对就好了. 一开始我还分别写了两个逆序对,想求个差的绝对值,发现样例过不了之后...... #include<cstdio>#include<algorithm>using namespace std;const in

【NOIP】提高组2013 火柴排队

[算法]求逆序对(树状数组)(也可以用归并排序等) [题解] 学自:http://blog.csdn.net/greatwjj/article/details/16808243 https://vijos.org/p/1842/solution(从下往上第三个回答) 因此要使结果最小,只要最大化aibi(i=1...n),即使小的数对应小的数,大的数对应大的数. 1.对于数列a,b先离散化,将他们值替换为他们在所在数列的排名. 2.令数列c记录a中每个数应该在b中的位置(a的目标位置). 3.对

NOIP2013 火柴排队

逆序对的经典题目.考试的时候不知道怎么写丑了,全WA了,正好带我复习了一遍逆序对. 将火柴序列从小到大分配一个等级,当a的等级与对应的b的等级相同时,答案最小,至于为什么是这样,我就不证明了.这里的等级,实际上就是离散化. 把a的等级从小到大排序之后,再把b对应a的等级排序,求出现在b的等级序列中的逆序对,就是我们要求的交换次数,因为每交换一次,只能使一组逆序对变成有序的. 注意暴搜求逆序对是要超时的,只能得70分,因此用树状数组求和才能过. #include<iostream> #inclu

BNUOJ 44662 水题 (贪心+优先级队列)

水题 Time Limit: 500ms Memory Limit: 32768KB This problem will be judged on HRBUST. Original ID: 2223 64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next 因为是有关于接水的问题,便简称为水题了(. N个人排队在M个出水口前接水,第i个人接水需时为t[i

Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对

题目:http://codevs.cn/problem/3286/ 3286 火柴排队  2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度.每列火柴中相

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<cs

火柴排队——重温逆序对

在vijos 的NOIP 历年题库中瞄到的,搞了搞.看来的确我刚开始学归并逆序对的时候就是一塌糊涂,据说还有树状数组求法,但是我树状数组更是一塌糊涂,以后再来加吧. 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 const int N=100086,M=99999997; 6 struct node{ 7 int x,p; 8 bool ope