首页 > 技术文章 > Codeforces 670C Cinema

AKMer 2018-09-24 21:38 原文

题目传送门:https://codeforces.com/problemset/problem/670/C

所谓离散化,就是将数值并不相邻的\(n\)个数据与\([1,n]\)之间的整数一一对应,并且相对大小关系依然满足原数列的相对大小关系。

比如\(1234,123,23,4245,2\)就可以转化成\(4,3,2,5,1\)。在原数列中两个值大小关系在新数列中依然不变。其实就相当于排名为\(rk\)的数在新数列中就是\(rk\)

那么,对于值域在\([-inf,inf]\)的复杂度与值域相关的问题,我们就可以把它的值域转化成\([1,n]\)了。

这道\(CF\)题目就是一个典型的排序加离散化好题……

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=2e5+5;

int n,m,tot;
int a[maxn],tmp[maxn*3],sum[maxn*3];//最多有maxn*3种语言

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}

struct MOVIE {
    int a,b,id;

    bool operator<(const MOVIE &mzf)const {
		if(sum[a]==sum[mzf.a]&&sum[b]==sum[mzf.b])return id<mzf.id;//原题是spj,不要这个也行
		if(sum[a]==sum[mzf.a])return sum[b]>sum[mzf.b];//语音相同就比字幕
		return sum[a]>sum[mzf.a];//直接比语音
    }
}movie[maxn];

int main() {
    n=read();
    for(int i=1;i<=n;i++)
		tmp[++tot]=a[i]=read();
    m=read();
    for(int i=1;i<=m;i++)
		tmp[++tot]=movie[i].a=read();
    for(int i=1;i<=m;i++)
		tmp[++tot]=movie[i].b=read();
    sort(tmp+1,tmp+tot+1);
    int cnt=unique(tmp+1,tmp+tot+1)-tmp-1;
    for(int i=1;i<=n;i++)
		a[i]=lower_bound(tmp+1,tmp+cnt+1,a[i])-tmp;
    for(int i=1;i<=m;i++) {
		movie[i].id=i;
		movie[i].a=lower_bound(tmp+1,tmp+cnt+1,movie[i].a)-tmp;
		movie[i].b=lower_bound(tmp+1,tmp+cnt+1,movie[i].b)-tmp;
    }//上面一段都是离散化
    for(int i=1;i<=n;i++)
		sum[a[i]]++;//sum[i]记录会i语言的科学家有多少个
    sort(movie+1,movie+m+1);//你也可以直接O(n)扫一遍,我是懒得写了emmm
    printf("%d\n",movie[1].id);
    return 0;
}

推荐阅读