关闭

线段树 1212. [NOIP2010冲刺十二] 奶牛排队

265人阅读 评论(0) 收藏 举报
分类:

奶牛在熊大妈的带领下排成了一条直队。
显然,不同的奶牛身高不一定相同……
现在,奶牛们想知道,如果找出一些连续的奶牛,要求最左边的奶牛A是最矮的,最右边的B是最高的,且B高于A奶牛,中间如果存在奶牛,则身高不能和A、B奶牛相同。问这样的奶牛最多会有多少头?
从左到右给出奶牛的身高,请告诉它们符合条件的最多的奶牛数(答案可能是0,2,但不会是1)。
【输入格式】

第一行一个数N (2≤N≤100000),表示奶牛的头数。
接下来N个数,每行一个数,从上到下表示从左到右奶牛的身高(1≤身高= maxlongint)。
【输出格式】

一行,表示最多奶牛数。
【样例输入】

5
1
2
3
4
1

这是题目:这道题可以用线段树,也可以直接暴力搜索

//这道题用线段树做感觉挺麻烦的,
#include <iostream>
#include <cstdio>

using namespace std;

const int maxn=100010;

int Read()
{
    char ch;
    int x;
    while(ch=getchar(),(ch<'0'||ch>'9'));
    x = ch-'0';
    while(ch=getchar(),(ch>='0' && ch <= '9'))
        x = x*10+ch-'0';
    return x;
}
int ans=0,h[maxn];

struct Node
{
    int L,R;
    int Max,Min;
};

Node Tree[maxn*2];

//建树的同时,插入Max,MIn,但是要确定最值得左边右边
void Build(int root,int l,int r)
{
    Tree[root].L = l,Tree[root].R =r;
    if(l==r)
    {
        Tree[root].Max=Tree[root].Min=l;
        return;
    }
    int mid = (l+r)>>1;
    Build(root<<1,l,mid);
    Build(root<<1|1,mid+1,r);
    if(h[Tree[root<<1].Max]>h[Tree[root<<1|1].Max])
        Tree[root].Max = Tree[root<<1].Max;
    else
        Tree[root].Max = Tree[root<<1|1].Max;
    if(h[Tree[root<<1].Min] < h[Tree[root<<1|1].Min])
        Tree[root].Min = Tree[root<<1].Min;
    else
        Tree[root].Min = Tree[root<<1|1].Min;
}

int Rmax(int a,int b)
{
    if(a>b) return a;
    return b;
}

int Rmin(int a,int b)
{
    if(a<b) return a;
    return b;
}

int get_max(int rt,int s,int t)
{
    if(s<=Tree[rt].L && t>=Tree[rt].R)
    {
        return Tree[rt].Max;
    }
    int mid = (Tree[rt].L+Tree[rt].R)/2;
    if(s>mid)
        return get_max(rt<<1|1,s,t);
    else if(t <= mid)
        return get_max(rt<<1,s,t);
    else
    {
        int a = get_max(rt<<1,s,mid);
        int b = get_max(rt<<1|1,mid+1,t);
        if(h[a]>h[b])
            return a;
        else
            return b;
    }
}

int get_min(int rt,int s,int t)
{
    if(s<=Tree[rt].L && t>=Tree[rt].R)
        return Tree[rt].Min;
    int mid = (Tree[rt].L+Tree[rt].R)/2;
    if(s>mid)
        return get_min(rt<<1|1,s,t);
    else if(t <= mid)
        return get_min(rt<<1,s,t);
    else
    {
        int a=get_min(rt<<1,s,mid);
        int b=get_min(rt<<1|1,mid+1,t);
        if(h[a]<h[b])
            return a;
        return b;
    }
}

//深度搜索
void dfs(int l,int r)
{
    if(l>=r || r-l+1<=ans)
        return;
    if(r-l == 1)
    {
        if(h[r]>h[l])
        {
            ans = Rmax(ans,2);
            return;
        }
    }
    int posmax=get_max(1,l,r);
    int posmin=get_min(1,l,r);
    if(h[posmax] == h[posmin])
        return;
    if(posmin<posmax)//要求posmin<posmax
        ans = Rmax(ans,posmax-posmin+1);
    dfs(l,posmin-1);
    dfs(posmin+1,posmax-1);
    dfs(posmax+1,r);
    //还不是很清楚这三个dfs是怎么回事
}

int main()
{
    freopen("tahort.in","r",stdin);
    freopen("tahort.out","w",stdout);
   int n=Read();
    bool flag=0;
    h[0] = 0x7f7f7f7f;
    for(int i=1;i<=n;i++)
    {
        h[i] = Read();
        if(h[i]>h[i-1])
            flag = 1;
    }
    if(!flag)
    {
        printf("0\n");
        return 0;
    }
    Build(1,1,n);
    dfs(1,n);
    printf("%d\n",ans);
    return 0;
}

暴力搜索,直接贴别人的代码了

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
using namespace std;  
int n;  
int a[100010];  
int ans;//记录答案   
bool flag;  
void work()  
{  
    for(int i=n;i>1;i--)  
    {  
        for(int j=i-1;j>=1;j--)  
        {  
            if(a[i]<=a[j]) break;//应当满足右边的点大于左边的点   
            flag=true;  
            for(int k=j+1;k<i;k++)  
            {  
                if(a[k]<=a[j]||a[k]>=a[i])//如果点k比左边的点小或比右边的大,表示i,j不为最大或最小   
                {  
                    flag=false;  
                    break;  
                }  
            }  
            if(flag)  
            {  
                ans=max(ans,i-j+1);  
                if(ans==n)//如果长度最长就为n则直接输出   
                {  
                    printf("%d",ans);   
                    return;//这里非常需要注意!!不能写成break,我最开始用break结果WA了3个点,因为如果不直接return,最后得出来的结果会输出两次   
                }  
            }  
        }  
    }   
    printf("%d",ans);  
}  
int main()  
{  
    freopen("tahort.in","r",stdin);  
    freopen("tahort.out","w",stdout);  
    scanf("%d",&n);  
    for(int i=1;i<=n;i++)  
    {  
        scanf("%d",&a[i]);  
    }  
    work();  
    return 0;  
}  
0
0
查看评论

[NOIP2010冲刺十二] 奶牛排队

1212. [NOIP2010冲刺十二] 奶牛排队 ★★   输入文件:tahort.in   输出文件:tahort.out   简单对比 时间限制:1 s   内存限制:128 MB 【题目描述】 奶牛...
  • qq_34004420
  • qq_34004420
  • 2016-10-25 17:09
  • 528

wikioi 1242 布局(奶牛排队) 差分约束

差分约束建图方法 第一: 感觉难点在于建图 第二: ①:对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值 ②:对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是...
  • Jackleg
  • Jackleg
  • 2016-11-12 19:31
  • 453

奶牛排队 (Standard IO)

题意/Description:        奶牛在熊大妈的带领下排成了一条直队。   显然,不同的奶牛身高不一定相同。。。。。   现在,奶牛们想知道,如果找出一些连续的奶牛,要求最左边的奶牛A是最矮的,最右边的B是最高的,且B高于A奶牛,中间如果存在...
  • peter_zhu01
  • peter_zhu01
  • 2016-07-16 12:07
  • 562

【USACO 2013 January Gold】奶牛排队

Description 农夫约翰的N(1 约翰觉得如果连续排列的一段奶牛有相同的血统编号的话,奶牛们看起来会更具有威猛。为了创造这样的连续段,约翰最多能选出k种血统的奶牛,并把他们全部从队列中赶走。请帮助约翰计算这样做能得到的由相同血统编号的牛构成的连续段的长度最大是多少? Input 第一行,两...
  • u012274244
  • u012274244
  • 2013-12-18 14:46
  • 1620

【NOIP2010冲刺十二模拟赛】奶牛晒衣服

Description在熊大妈英明的带领下,时针和它的同伴生下了许多牛宝宝。熊大妈决定给每个宝宝都穿上可爱的婴儿装。于是,为牛宝宝洗晒衣服就成了很不爽的事情。 圣人王担负起了这个重任。洗完衣服后,你就要弄干衣服。衣服在自然条件下用1的时间可以晒干A点湿度。抠门的熊大妈买了1台烘衣机。使用烘衣机可...
  • qq_35493599
  • qq_35493599
  • 2016-11-13 15:47
  • 186

COGS1212. 奶牛排队

奶牛在熊大妈的带领下排成了一条直队。   显然,不同的奶牛身高不一定相同…… 现在,奶牛们想知道,如果找出一些连续的奶牛,要求最左边的奶牛A是最矮的,最右边的B是最高的,且B高于A奶牛,中间如果存在奶牛,则身高不能和A、B奶牛相同。问这样的奶牛最多会有多少头? 从左到右给出奶牛的身高,...
  • ScaPrt
  • ScaPrt
  • 2017-05-13 13:40
  • 311

【noip2010】接水问题

【noip】接水问题 描述 学校里有一个水房,水房里一共装有m 个龙头可供同学们打开水,每个龙头每秒钟的 供水量相等,均为1。 现在有n 名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从1 到n 编号,i 号同学的接...
  • Clove_unique
  • Clove_unique
  • 2015-10-29 18:33
  • 1611

奶牛排队

奶牛排队 ★★   输入文件:tahort.in   输出文件:tahort.out   简单对比 时间限制:1 s   内存限制:128 MB 【题目描述】 奶牛在熊大妈的带领下排成了一条直队...
  • yhb1216776494
  • yhb1216776494
  • 2013-08-13 10:20
  • 890

小试5

冲刺NOIP2017模拟赛1 题目名称 奶牛晒衣服 奶牛排队 圆圈舞蹈 存盘文件名 dry tahort circle 输入文件名 dry.in tahort.in circle.in 输出文件名 dry.out tahort.out circle.out 时限 1s 1s...
  • no1_terminator
  • no1_terminator
  • 2017-09-10 09:13
  • 120

POJ 2828 排队插队(线段树_好题)

Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue… The Lunar New...
  • h1021456873
  • h1021456873
  • 2016-03-09 14:58
  • 543
    个人资料
    • 访问:11759次
    • 积分:691
    • 等级:
    • 排名:千里之外
    • 原创:56篇
    • 转载:18篇
    • 译文:0篇
    • 评论:0条