acdream(18) Disappeared Block(离散化+二分)

题目链接:点击打开链接


把图形想象成一个波,对于波峰如果被没过去,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;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值