题目链接:点击打开链接
把图形想象成一个波,对于波峰如果被没过去,part数会减一,对于波谷被没过去part数会加1。所以要预处理出所有的波峰和波谷。
两个端点属于特殊情况,可以选择把h[0]和h[n+1]设为-1的方法。
然后把只含波峰波谷的数组按高度(即发生变化的时间)从大到小排序,依次计算此时part数,此处要注意如果有好几个相同高度的点,但他们是不连续的,要把这些点全部处理完后的最终值作为这些点的答案,因为变化是一起发生的。此处wa了一次。
最后2分搜索答案即可。
代码:
#include <iostream>
#include<cstdlib>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#define MAX 1000000+10
using namespace std;
int h[MAX];
int Q[MAX];
int res[MAX];
struct node{
int height;
bool up;
}p[MAX];
bool cmp(node a,node b){
return a.height<b.height;
}
int bs(node a[],int len,int n){
int l=1,r=len;
while(l<r){
int m=(l+r)>>1;
if(a[m].height<=n&&a[m+1].height>n){
return m;
}
else if(a[m].height>n){
r=m-1;
}
else l=m+1;
}
return r;
}
int main(){
int T;
int flag=1;
cin>>T;
while(T--){
int n,m;
scanf("%d%d",&n,&m);
h[0]=-1;
h[n+1]=-1;
for(int i=1;i<=n;i++){
scanf("%d",&h[i]);
}
int num=0;
int l,r;
for(int i=1;i<=n;i++){
l=i;
while(h[i]==h[i+1]) i++;
r=i;
if(h[l]>h[l-1]&&h[l]>h[r+1]){
p[++num].up=1;
p[num].height=h[l];
}
else if(h[l]<h[l-1]&&h[l]<h[r+1]){
p[++num].up=0;
p[num].height=h[l];
}
}
sort(p+1,p+num+1,cmp);
int init=1;
for(int i=1;i<=num;i++){
int t=p[i].height;
int j=i;
while(1){
if(p[j].up==1) init--;
else init++;
if(j>=num) break;
else if(p[j+1].height==t) j++;
else break;
}
for(int k=i;k<=j;k++){
res[k]=init;
// cout<<k<<" "<<res[k]<<endl;
}
i=j;
}
int ans;
printf("Case #%d:",flag++);
for(int i=1;i<=m;i++){
int t;
scanf("%d",&t);
int pos;
if(p[1].height>t) ans=1;
else if(p[num].height<t) ans=0;
else{
int pos=bs(p,num,t);
ans=res[pos];
}
printf(" %d",ans);
}
printf("\n");
}
return 0;
}