[P1311][NOIP2011]选择客栈

原题链接

不知道标准正解是啥
用了个有点奇葩的线段树
记录[l,r]这段区间内
第一个价格<=p的位置

有一个写起来异常简洁的思路
而且是O(n)复杂度
在这里贴一下链接
戳我(。・ω・。)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<climits>
#include<queue>
#include<vector>
#include<ctime>
#define LL long long
#define maxn 200005
using namespace std;

int n,k,p,cl[maxn],mon[maxn],mr[4*maxn],tot[55],pos[55][maxn],ans;

void build(int id,int l,int r)
{
    if(l==r) 
    {
        if(mon[l]<=p) mr[id]=l;
        else mr[id]=maxn;
        return;
    }

    int mid=(l+r)>>1;

    build(id<<1,l,mid);
    build((id<<1)|1,mid+1,r);

    mr[id]=min(mr[id<<1],mr[(id<<1)|1]);        
}

int search(int id,int l,int r,int lef,int rig)
{
    int mid=(l+r)>>1;

    if(lef>r||rig<l) return maxn;
    if(lef<=l&&rig>=r) return mr[id];

    if(rig<=mid) return search(id<<1,l,mid,lef,rig);    
    if(lef>mid) return search((id<<1)|1,mid+1,r,lef,rig);

    return min(search(id<<1,l,mid,lef,mid),search((id<<1)|1,mid+1,r,mid+1,rig));
}

int main()
{
    freopen("hotel.in","r",stdin);
    freopen("hotel.out","w",stdout);    

    int c,i,j,r,q;

    scanf("%d%d%d",&n,&k,&p); 

    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&cl[i],&mon[i]);
        c=cl[i];

        tot[c]++;
        pos[c][tot[c]]=i;
    }

    build(1,1,n);   

    for(i=0;i<k;i++)
        for(j=1;j<tot[i];j++)
        {
            if(mon[pos[i][j]]<=p)
            {
                ans=ans+tot[i]-j;
                continue;
            }

            r=search(1,1,n,pos[i][j],n);//求出最近到哪一个位置才能<=p 
            if(r==maxn) continue;

            q=lower_bound(pos[i]+j+1,pos[i]+tot[i]+1,r)-pos[i];
            ans=ans+tot[i]-q+1;
        }

    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值