codeforces 670C_Cinema

源头:https://www.cnblogs.com/AKMer/p/9696824.html

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

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

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

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

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

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

空间复杂度:O(n)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;
}

猜你喜欢

转载自blog.csdn.net/qq_35937273/article/details/82841195