差分:2020CCPC秦皇島 D Exam Results
阿新 • • 發佈:2020-12-20
技術標籤:差分字首和
題目連結:點選這裡
#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;
}