• 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;
    }
    
  • 相关阅读:
    获取文件夹下的所有子文件,读取TXT文档
    360笔试
    刷题总结
    背包问题
    二叉树的创建、层次遍历、前序遍历、中序遍历、后序遍历
    今日头条面试
    面试题目
    Java高并发秒杀优化
    配置tomcat解压版
    环境变量设置:
  • 原文地址:https://www.cnblogs.com/Absofuckinglutely/p/12382698.html
Copyright © 2020-2023  润新知