洛谷1966 火柴排队

洛谷1966 火柴排队


原题链接


交题记录

23:33 10'
23:38 10'
23:40 0'
15:32 AC


题解

首先肯定要先离散化然后根据排名一一对应
怎么交换?
肯定可以一个不动另一个动去交换
那么怎么办?重新赋一个标号。
将a变成1 2 3 4 5 ... n,答案就是b的逆序对数。
那么假设\(f[a]==b\)表示a中标号a变成b,实现方法就是

for i=1...n do f[a[i]]=i

a重新赋标号之后再给b重新赋标号。

for i=1...n do b[i]=f[b[i]]

整合一下

for i=1...n do f[a[i]]=i
for i=1...n do b[i]=f[b[i]]

需要注意的是求b的逆序对数就用不到a了


Code

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define lb(o) (o&-o)
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int maxn=100010;
int a[maxn],b[maxn];
int p[maxn],q[maxn];
int n;
int f[maxn];
int tree[maxn];
il vd add(int pos){while(pos<=n)++tree[pos],pos+=lb(pos);}
il int sum(int pos){int ret=0;while(pos)ret+=tree[pos],pos-=lb(pos);return ret;}
int main(){
    n=gi();
    rep(i,1,n)a[i]=p[i]=gi();
    rep(i,1,n)b[i]=q[i]=gi();
    sort(p+1,p+1+n);
    sort(q+1,q+1+n);
    rep(i,1,n)a[i]=lower_bound(p+1,p+1+n,a[i])-p;
    rep(i,1,n)b[i]=lower_bound(q+1,q+1+n,b[i])-q;
    rep(i,1,n)f[a[i]]=i;
    rep(i,1,n)b[i]=f[b[i]];
    int ans=0;
    rep(i,1,n)add(b[i]),ans=(ans+i-sum(b[i]))%99999997;
    printf("%d\n",ans);
    return 0;
}


这里还有一种解法我不太懂。。。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define lb(o) (o&-o)
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int maxn=100010;
struct num{
    int s,id;
    bool operator < (num o){return s<o.s;}
}a[maxn],b[maxn];
int n;
int t[maxn];
int tree[maxn];
il vd add(int pos){while(pos<=n)++tree[pos],pos+=lb(pos);}
il int sum(int pos){int ret=0;while(pos)ret+=tree[pos],pos-=lb(pos);return ret;}
int main(){
    n=gi();
    rep(i,1,n)a[i]=(num){gi(),i};
    rep(i,1,n)b[i]=(num){gi(),i};
    sort(a+1,a+1+n);
    sort(b+1,b+1+n);
    rep(i,1,n)t[a[i].id]=b[i].id;
    int ans=0;
    rep(i,1,n)add(t[i]),ans=(ans+i-sum(t[i]))%99999997;
    printf("%d\n",ans);
    return 0;
}
posted @ 2017-08-26 15:34  菜狗xzz  阅读(107)  评论(0编辑  收藏  举报