zoukankan      html  css  js  c++  java
  • BZOJ 3314 [Usaco2013 Nov]Crowded Cows:单调队列

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3314

    题意:

      N头牛在一个坐标轴上,每头牛有个高度。现给出一个距离值D。

      如果某头牛在它的左边,在距离D的范围内,如果找到某个牛的高度至少是它的两倍,且在右边也能找到这样的牛的话。则此牛会感觉到不舒服。

      问有多少头会感到不舒服。

    题解:

      从左到右、从右到左两遍单调队列。

      单调性:

        (1)坐标x递增。

        (2)高度h递减。

      维护单调性:

        (1)从队首开始,所有与当前牛i的距离超过d的,以后都不会再用到。

        (2)从队尾开始,所有高度 <= 当前高度h[i]的,都不会再用到,因为当前牛i一定比前面的更优(又高又近)。

        (3)最后再将i压入队尾。

      每次判断一下之前最高的牛(队首)是不是h[i]的两倍,如果是则cnt[i]++。

      最后统计一下cnt[i] == 2的个数就好。

    AC Code:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define MAX_N 50005
    
    using namespace std;
    
    struct Data
    {
        int x;
        int h;
        Data(int _x,int _h)
        {
            x=_x;
            h=_h;
        }
        Data(){}
        friend bool operator < (const Data &a,const Data &b)
        {
            return a.x<b.x;
        }
    };
    
    int n,d;
    int head;
    int tail;
    int ans=0;
    int q[MAX_N];
    int cnt[MAX_N];
    Data dat[MAX_N];
    
    void read()
    {
        cin>>n>>d;
        for(int i=0;i<n;i++)
        {
            cin>>dat[i].x>>dat[i].h;
        }
    }
    
    void solve()
    {
        sort(dat,dat+n);
        memset(cnt,0,sizeof(cnt));
        head=0;
        tail=0;
        for(int i=0;i<n;i++)
        {
            while(head<tail && dat[i].x-dat[q[head]].x>d) head++;
            while(head<tail && dat[q[tail-1]].h<=dat[i].h) tail--;
            if(head<tail && dat[q[head]].h>=dat[i].h*2) cnt[i]++;
            q[tail++]=i;
        }
        head=0;
        tail=0;
        for(int i=n-1;i>=0;i--)
        {
            while(head<tail && dat[q[head]].x-dat[i].x>d) head++;
            while(head<tail && dat[q[tail-1]].h<=dat[i].h) tail--;
            if(head<tail && dat[q[head]].h>=dat[i].h*2) cnt[i]++;
            q[tail++]=i;
        }
        for(int i=0;i<n;i++)
        {
            if(cnt[i]==2) ans++;
        }
    }
    
    void print()
    {
        cout<<ans<<endl;
    }
    
    int main()
    {
        read();
        solve();
        print();
    }
  • 相关阅读:
    win10新特性,ubuntu子系统(安装及配置)
    excel计算后列填充
    word中利用宏替换标点标点全角与半角
    CFD-post的奇技淫巧
    mfix模拟流化床燃烧帮助收敛的方法
    cygwin下配置alias
    endnote 使用方法
    win8系统换win7系统
    python中的函数以及递归
    01python算法--算法和数据结构是什么鬼?
  • 原文地址:https://www.cnblogs.com/Leohh/p/7648857.html
Copyright © 2011-2022 走看看