1. 程式人生 > 其它 >差分:2020CCPC秦皇島 D Exam Results

差分: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; }