2020年上学期第二场——FJUT&FJNU友谊赛 G题 联谊活动

### 题目链接 ###

题目大意:给定男生与女生的移动区间,问每个男生最大能遇上多少位女生。


分析:
1、每个男生的区间内,与多少个女生的区间重合,即为题目所求的能遇见的最大女生人数。

2、对于某个男生,假定他的区间为 ([) (L) (,) (R) (]),而第 (i) 位的女生区间为 ([) (l)(i) (,) (r)(i) (])

显然,对于某个男生而言,女生们的区间可以分为这五类,而对答案做贡献的是第 2 、3 、4 号区间。

观察一下可以发现,这些有贡献的区间会满足,(l) (≤) (R)

而第一号区间也满足 (l) (≤) (R) 却不做贡献,是因为它的 (r) (<) (L)

3、故我们要求某一个男生的贡献,只需要统计有多少位女生的 (l)(≤) 男生的 (R) 而又满足女生的 (r) (≥) 男生的 (L) ,即查询比 (l) (≤) (R) 的女生区间个数 减去 那些 (r) (<) (L) 的女生区间个数(注意没有等号)。

二分做法:
记录两个数组 (a[])(b[]),分别表示女生区间以 (l) 从小到大排序 和 女生区间以 (r) 从小到大排序。
对于某个男生的区间([) (L) (,) (R) (]) ,在 (a[]) 中找到最后一个小于等于 (R) 的位置 (pos) ,则第 (1) ~ (pos) 号区间都满足 (l) (≤) (R)
(b[]) 中找到最后一个小于等于 (L)的位置 (或第一个大于 (L) 的位置 ),位置对减即可。

代码如下:

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = 200008;
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const ll INF = 1e18 + 10;
const double eps = 1e-6;
using namespace std;
int n,m;
ll ans;
struct People{
	int l,r;
}a[maxn],b[maxn],c[maxn];
bool cmp1(People q,People w){
	return q.r<w.r;
}
bool cmp2(People q,People w){
	return q.l<w.l;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].l,&a[i].r);
	for(int i=1;i<=m;i++) scanf("%d%d",&b[i].l,&b[i].r),c[i].l=b[i].l,c[i].r=b[i].r;
	sort(b+1,b+m+1,cmp1);
	sort(c+1,c+m+1,cmp2);
	for(int i=1;i<=n;i++){
		int st=lower_bound(b+1,b+m+1,People{0,a[i].l},cmp1)-b;
		int en=upper_bound(c+1,c+m+1,People{a[i].r,0},cmp2)-c-1;
		if(i!=n)printf("%d
",en-st+1);
		else printf("%d", en-st+1);
	}
	return 0;
}

树状数组同理,需要离散化:
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = 200008;
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const ll INF = 1e18 + 10;
const double eps = 1e-6;
using namespace std;
int n,m;
int c[maxn<<2][2],f[maxn<<2];
struct People{
	int l,r;
}a[maxn],b[maxn];
inline int lowbit(int x){return x&(-x);}
void update(int i,int x){
	while(i<=800000){
		c[i][x]++;
		i+=lowbit(i);
	}
	return;
}
int query(int i,int x){
	int ans=0;
	while(i){
		ans+=c[i][x];
		i-=lowbit(i);
	}
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	int cnt=0;
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&a[i].l,&a[i].r);
		f[++cnt]=a[i].l,f[++cnt]=a[i].r;
	}
	for(int i=1;i<=m;i++){
		scanf("%d%d",&b[i].l,&b[i].r);
		f[++cnt]=b[i].l,f[++cnt]=b[i].r;
	}
	sort(f+1,f+cnt+1);
	int len=unique(f+1,f+cnt+1)-f-1;
	int st,en;
	for(int i=1;i<=m;i++){
		st=lower_bound(f+1,f+len+1,b[i].l)-f;
		en=lower_bound(f+1,f+len+1,b[i].r)-f;
		update(st,0),update(en,1);
	}
	for(int i=1;i<=n;i++){
		st=lower_bound(f+1,f+len+1,a[i].l)-f;
		en=lower_bound(f+1,f+len+1,a[i].r)-f;	
		printf("%d
",query(en,0)-query(st-1,1));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Absofuckinglutely/p/12382698.html