电影

电影

给出一个长度为n的数列({a_i})和一个长度为m的二元组数列({b_i,c_i}),现在请寻找一个二元组({b_i,c_i})使得第一元在a数列中出现次数尽可能多的前提下,第二元在a中出现的次数尽可能多,(1≤n,m≤200000)

显然数据范围支持我们枚举选哪个二元组,于是问题就转化成如何快速查询一个数字在数列a中出现的次数,自然想到桶排,但是注意到序列a的数字范围过大,于是可以考虑离散化或者hash,然后就可以做到(O(log(n)))或者(O(1))查询。

但要注意的几点是可能二元组的某些数在序列中压根没出现过,这个要特判为0.

参考代码:

离散化

#include <iostream>
#include <cstdio>
#include <algorithm>
#define il inline
#define ri register
#define Size 200050
using namespace std;
struct lsh{
	int a[Size],b[Size],n;
	il void prepare(int size,int ar[]){n=size;
		for(ri int i(1);i<=n;++i)a[i]=ar[i];sort(a+1,a+n+1);
		for(ri int i(1);i<=n;++i)b[i]=dfs(ar[i]);
	}
	il int dfs(int x){
		int l(1),r(n),mid;
		while(l<=r){
			mid=l+r>>1;
			if(a[mid]<x)l=mid+1;
			else r=mid-1;
		}if(a[l]==x)return l;
		return 0;
	}
}L;
struct pi{
	int b,c;
}p[Size],hl;
int a[Size],bu[Size];
il void read(int&);
int main(){
	int n,m,czf;read(n);
	for(int i(1);i<=n;++i)read(a[i]);read(m);
	for(int i(1);i<=m;++i)read(p[i].b);
	for(int i(1);i<=m;++i)read(p[i].c);
	L.prepare(n,a);
	for(int i(1);i<=n;++i)++bu[L.b[i]];
	for(int i(1),j;i<=m;++i){
		j=L.dfs(p[i].b);
		if(bu[j]>hl.b)hl.b=bu[j],hl.c=bu[L.dfs(p[i].c)],czf=i;
		else if(bu[j]==hl.b){j=L.dfs(p[i].c);
			if(bu[j]>hl.c)hl.c=bu[j],czf=i;
		}
	}printf("%d",czf);
	return 0;
}
il void read(int &x){
	x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

hash

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define Size 200100
#define czf 1188839
using namespace std;
struct unordered_map{
	struct DATA{
		DATA*next;int d,b;
	}*head[czf],*pt;
	il void insert(int d){
		int H(d%czf);pt=new DATA;
		pt->next=head[H],pt->d=d,pt->b=1;
		head[H]=pt;
	}
	il DATA* find(int d){
		for(pt=head[d%czf];pt!=NULL;pt=pt->next)
			if(pt->d==d)return pt;return NULL;
	}
}un;
struct pi{
	int b,c;
}p[Size],hl;
int a[Size];
il void read(int&);
int main(){int n,m,lsy(1);read(n);
	for(int i(1);i<=n;++i)read(a[i]);read(m);
	for(int i(1);i<=m;++i)read(p[i].b);
	for(int i(1);i<=m;++i)read(p[i].c);
	for(int i(1);i<=n;++i)
		if(un.find(a[i])==NULL)un.insert(a[i]);
		else ++un.find(a[i])->b;
	for(int i(1);i<=m;++i){
		if(un.find(p[i].b)==NULL)continue;
		if(un.find(p[i].b)->b>hl.b){
			hl.b=un.find(p[i].b)->b,lsy=i;
			if(un.find(p[i].c)==NULL){hl.c=0;continue;}
			hl.c=un.find(p[i].c)->b;
		}
		else if(un.find(p[i].b)->b==hl.b){
			if(un.find(p[i].c)==NULL)continue;
			if(un.find(p[i].c)->b>hl.c)
				hl.c=un.find(p[i].c)->b,lsy=i;
		}
	}printf("%d",lsy);
	return 0;
}
il void read(int &x){
	x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/11213510.html