Description
有個腦筋急轉彎是這樣的:有距離很近的一高一低兩座橋,兩次洪水之後高橋被淹了兩次,低橋卻只被淹了一次,爲什麼?答案是:因爲低橋太低了,第一次洪水退去之後水位依然在低橋之上,所以不算“淹了兩次”。舉例說明:
假定高橋和低橋的高度分別是5和2,初始水位爲1
第一次洪水:水位提高到6(兩個橋都被淹),退到2(高橋不再被淹,但低橋仍然被淹)
第二次洪水:水位提高到8(高橋又被淹了),退到3。
沒錯,文字遊戲。關鍵在於“又”的含義。如果某次洪水退去之後一座橋仍然被淹(即水位不小於橋的高度),那麼下次洪水來臨水位提高時不能算“又”淹一次。
輸入n座橋的高度以及第i次洪水的漲水水位ai和退水水位bi,統計有多少座橋至少被淹了k次。初始水位爲1,且每次洪水的漲水水位一定大於上次洪水的退水水位。
Input
輸入文件最多包含25組測試數據。每組數據第一行爲三個整數n, m, k(1<=n,m,k<=105)。第二行爲n個整數hi(2<=hi<=108),即各個橋的高度。以下m行每行包含兩個整數ai和bi(1<=bi<ai<=108, ai>bi-1)。輸入文件不超過5MB。
Output
對於每組數據,輸出至少被淹k次的橋的個數。
Sample Input
2 2 22 56 28 35 3 22 3 4 5 65 34 25 2
Sample Output
Case 1: 1Case 2: 3
Hint
Source
湖南省第九屆大學生計算機程序設計競賽#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=1e5+5;
int n,m,k;
int a[maxn],c[maxn],x[maxn],y[maxn];
int lowbit(int k1)
{
return k1&(-k1);
}
int add(int p,int q)//對某一座橋被淹次數進行操作
{
while(p>0)
{
c[p]+=q;
p-=lowbit(p);
}
return 0;
}
//int count1=1;
int search1(int p)//二分查找到指定位置
{
int mid,temp=p;
int rs=n,ls=1;
while(rs>ls)
{
mid=((rs+ls)>>1);
if(a[mid]>=temp)
{
rs=mid;
}
else ls=mid+1;
}
return rs;
}
int sum(int p)//求出p位置總共被淹了幾次
{
int kk=0;
while(p<=n)
{
kk+=c[p];
p+=lowbit(p);
}
return kk;
}
int main()
{
int cnt=0;
while(scanf("%d %d %d",&n,&m,&k)!=EOF)
{
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
int p,q,ans,kk;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
//cout<<x[i]<<" "<<y[i]<<endl;
if(i==1)
{
p=i;
q=search1(x[i]);
//printf("")
//cout<<123456<<endl;
}
else
{
p=search1(y[i-1]);//找到上次退潮橋被淹的橋的最高序號,因爲拍過序p,所以小與p的都不用加次數,因爲都在水裏
q=search1(x[i]);//找到比這次漲潮高度要淹的最高序號q,q與q之下的都要被淹
}
add(p,-1);//對小與上次退潮高度的橋被淹次數減1,抵消下面的加1操作
add(q,1);//對小與這次漲潮高度的橋被淹次數加1
}
ans=0;
for(int i=1;i<=n;i++)
{
kk=sum(i);
//cout<<kk<<" "<<k<<endl;
if(kk>=k)
ans++;
}
printf("Case %d: %d\n",++cnt,ans);
}
}