noip2013提高组day1第二题火柴排队
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip2013提高组day1第二题火柴排队相关的知识,希望对你有一定的参考价值。
各路大侠能否解释一下noip2013提高组day1第二题火柴排队怎么做,附上C语言代码更好!万分感谢
首先 先了解排序不等式 可证明 只有第一列的第i大火柴和第二列的第i大火柴在一起的时候 才会符合要求然后思路就很清晰了 你有两条路:
暴力之 先快排一个 然后用二分查找 调换 据说这么做就有七十分了真是丧心病狂.....如果你更蛋疼一点的话 可以试试看用 stl模版中的vector 没准能过ac.......没准
正解方法 先对两个排序 然后求逆序对.......这么说可能太笼统 举个例子
设 第一个序列是32145 第二个序列是52143
第二个序列排成第一个,那么相当于第二个序列中
5应当排第5个
2应当排第2个
1应当排第3个
4应当排第4个
3应当排第1个
于是就是求52341的逆序对,7个
逆序对和快排你一定都会打了 那就这样吧...
提供c++版本ac代码.........
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int d[1000001];
long long ans=0;
void stablesort(int *a,int l,int mid,int r)
int i=l,j=mid+1,k=l;
while (i<=mid && j<=r)
if (a[i]<=a[j]) d[k++]=a[i++];
else d[k++]=a[j++]; ans+=mid+1-i;ans=ans%99999997;
while (i<=mid)
d[k++]=a[i++];
while (j<=r)
d[k++]=a[j++];
for (int q=l;q<=r;q++) a[q]=d[q];
void merge(int *a,int l,int r)
if (l<r)
int mid=(l+r)/2;
merge(a,l,mid);
merge(a,mid+1,r);
stablesort(a,l,mid,r);
int n,c[1000001];
struct data
int xx,yy;a[1000001],b[1000001];
inline int cmp(const void *a,const void *b)
if ( (*(data *)a) .xx < (*(data *)b) . xx )
return 1;
else return -1;
int main()
scanf("%d",&n);
for (int q=0;q<n;q++) scanf("%d",&a[q].xx);a[q].yy=q;
for (int q=0;q<n;q++) scanf("%d",&b[q].xx);b[q].yy=q;
qsort(a,n,sizeof(data),cmp);
qsort(b,n,sizeof(data),cmp);
for (int q=0;q<n;q++)
c[b[q].yy]=a[q].yy;
merge(c,0,n-1);
printf("%d",ans);
//system("pause");
return 0;
(因为我只会c++) 参考技术A 首先贪心只有第一列的第i大火柴和第二列的第i大火柴在一起的时候才会符合要求。
那要如何求距离呢??用逆序对。
用树状数组求出逆序对。
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<ctype.h>
#include<ctime>
#include<set>
#include<map>
#include<memory.h>
#include<cstring>
#include<iostream>
#include<fstream>
#include<vector>
#include<functional>
#include<queue>
#include<cassert>
#include<numeric>
#include<utility>
#include<deque>
#include<stack>
#include<bitset>
#include<list>
#include<iomanip>
#include<stdexcept>
#include<complex>
#include<iterator>
#define x first
#define y second
#define mp make_pair
using namespace std;
const int MAX=(1<<30);
pair<int,int>q[100001],q1[100001];
int pp[100001],s[100001];
int i,j,k,m,n;
const int mod=99999997;
int lowbit(int x)
return x&(-x);
int sum(int x)
int su=0;
while(x)
x-=lowbit(x);
su+=s[x],su%=mod;
return su;
int add(int x)
while(x<=n)
s[x]++,s[x]%=mod;
x+=lowbit(x);
return 0;
int main()
cin>>n;
for(i=1;i<=n;i++)
scanf("%d",&k),
q[i]=mp(k,i);
for(i=1;i<=n;i++)
scanf("%d",&k),
q1[i]=mp(k,i);
sort(q+1,q+n+1);
sort(q1+1,q1+n+1);
for(i=1;i<=n;i++)
pp[q[i].y]=q1[i].y;
for(i=n;i>0;i--)
m+=sum(pp[i])%mod,m%=mod,add(pp[i]+1);
cout<<m<<endl;
return 0;
NOIP2013提高组火柴排队
https://www.luogu.org/problem/show?pid=1966
Σ(ai-bi)2=Σai2+Σbi2-2Σai*bi,要使Σ(ai-bi)2最小,则需2Σai*bi最大。
由排序不等式可知两列数字里第一大与第一大对应,第二大与第二大对应,……,第k大与第k大对应,……,第n大与第n大对应时,Σai*bi最大。
故先将第一列每个数字映射到第二列排名相同的数字,再求需要交换的次数,也就是逆序对的个数。
#include <algorithm> #include <iostream> #include <vector> #define maxn 100005 typedef long long llint; using namespace std; int n; llint tmp[maxn], sorted[maxn], cnt = 0; 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); int p1 = l, p2 = mid + 1, p = l; while (p1 <= mid && p2 <= r) { if (sorted[p1] <= sorted[p2]) tmp[p++] = sorted[p1++]; else { cnt = (cnt + (mid - p1 + 1)) % 99999997; tmp[p++] = sorted[p2++]; } } while (p1 <= mid) tmp[p++] = sorted[p1++]; while (p2 <= r) tmp[p++] = sorted[p2++]; for (int i = l; i <= r; i++) sorted[i] = tmp[i]; } template <class T> void print(T *p) { for (int i = 1; i <= n; i++) cout << p[i] << ‘ ‘; cout << endl; } pair<llint, llint> a[maxn], b[maxn]; int rnk[maxn]; int main() { ios::sync_with_stdio(false); cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i].first; a[i].second = i; } for (int i = 1; i <= n; i++) { cin >> b[i].first; b[i].second = i; } sort(a + 1, a + n + 1); sort(b + 1, b + n + 1); for (int i = 1; i <= n; i++) sorted[a[i].second] = b[i].second; // 将第一列排第i名的项与第二列排第i名的项对应 merge_sort(1, n); cout << cnt << endl; return 0; }
以上是关于noip2013提高组day1第二题火柴排队的主要内容,如果未能解决你的问题,请参考以下文章
Vijos P1496 火柴棒等式 NOIP2008提高组第二题