差分:2020CCPC秦皇岛 D Exam Results

题目链接:点击这里

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>//差分+离散化
//差分性质:1.差分序列求前缀和可得到原序列
//2.原序列[l,r]区间内所有元素+k,转化为差分序列l处+k,r+1处-k; 
//对于每一个分数,都有一个分数上限和分数下限,在这个区间内的所有分数都可以使它及格
//可很显然,1<=bi<=ai<=1e9,爆内存
//开一个数组储存一下每个分数上下限,用lower_bound定位对应分数下限或上限的下标   这个过程叫做离散化
//及格就让这个区间内的每个分数对应的及格人数+1(用差分数组这个时间复杂度为O(1))
//现在每个分数对应的及格人数有了,遍历一遍分数找到及格最多的人数即可
//注意由于是以最高分为标准的,也就是要从差成绩中最高的开始算起  //差分
using namespace std;
typedef long long ll;
ll ans[800005],diff[800005],a[200005],b[200005];
int main(){
    
    
    int t;
    scanf("%d",&t);
    for(int hy=1;hy<=t;++hy){
    
    
    	ll n,p,cnt=0,sum=0,kk=0,ok=0;
    	scanf("%lld%lld",&n,&p);
    	for(ll i=0;i<=4*n+2;++i) diff[i]=0;
    	for(ll i=0;i<n;++i){
    
    
    		scanf("%lld%lld",&a[i],&b[i]);
    		ans[cnt++]=b[i],ans[cnt++]=b[i]*100/p,ans[cnt++]=a[i],ans[cnt++]=a[i]*100/p;
    		if(b[i]>ok) ok=b[i];
		}
		sort(ans,ans+cnt);//logn
		for(ll i=0;i<n;++i){
    
    //nlogn  //把符合的区间人数+1 
			ll minn=b[i],minm=b[i]*100/p,maxn=a[i],maxm=a[i]*100/p;
			ll pos1=lower_bound(ans,ans+cnt,minn)-ans;//低分数下限 
			ll pos2=lower_bound(ans,ans+cnt,minm)-ans;//低分数上限 
			ll pos3=lower_bound(ans,ans+cnt,maxn)-ans;//高分数下限 
			ll pos4=lower_bound(ans,ans+cnt,maxm)-ans;//高分数上限
			if(pos2<pos3){
    
    
				++diff[pos1],--diff[pos2+1],++diff[pos3],--diff[pos4+1];
			}// [pos1,pos2] 和 [pos3,pos4] 区间内+1 
			else{
    
    
				++diff[pos1],--diff[pos4+1];
			}//[pos1,po4]区间内+1 
		}
		for(ll i=0;i<cnt;++i){
    
    
			sum=sum+diff[i];
			if(ans[i]>=ok&&sum>kk){
    
    
				kk=sum;
			}//保证取到的是最高分(不然以最低分为标准肯定都会及格,人数最多)
		}
		printf("Case #%d: %lld\n",hy,kk);
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45695839/article/details/111399650