UvaLive 6531 Go up the ultras

链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4542

题意:有N个山峰,(N<=10^5),每个山峰有高度h,对应着每个山峰有一个d值,每个山峰到所有其他的严格比它高的山峰都会经过一个最低值(山谷),d代表是h减去这些最低值中的最大值的差(如果不存在比它高的山峰那么d就是它本身的高度),问有多少山峰的d>=150000米。

思路:题读起来还是蛮有难度的,对于山峰p,题目所要求的d的值所需要的最高的山谷一定出现在这p与和它相邻的两个比它高的山峰之间。这样问题就转化成了确定两边第一个比它高的山峰,并找到这两个之间的最小值(山谷)。找到第一个比它高的山峰用dp,询问最小值用rmq。

代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define maxn 100005
#define PI acos(-1.0)
#define seed 31//131,1313
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
int val[maxn*4],aa[maxn];
int t;
void build(int i,int l,int r)
{
    if(l==r)
    {
        scanf("%d",&val[i]);
        aa[l]=val[i];
        return ;
    }
    int mid=(l+r)>>1;
    build(lson),build(rson);
    val[i]=min(val[i<<1],val[i<<1|1]);
}
int query(int i,int l,int r,int q_l,int q_r)
{
    if(q_l<=l&&r<=q_r) return val[i];
    int mid=(l+r)>>1;
    if(q_r<=mid) return query(lson,q_l,q_r);
    else if(q_l>mid) return query(rson,q_l,q_r);
    else return min(query(rson,mid+1,q_r),query(lson,q_l,mid));
}
int L[maxn],R[maxn];
void init()
{
    memset(L,0,sizeof(L));
    memset(R,0,sizeof(R));
    memset(aa,-1,sizeof(aa));
    memset(val,0,sizeof(val));
    build(1,1,t);
}
int main()
{
    while(~scanf("%d",&t))
    {
        init();
        L[1]=0;
        for(int i=2; i<=t; i++)
        {
            if(aa[i-1]>aa[i])
                L[i]=i-1;
            else
            {
                int from=i-1;
                while(aa[i]>=aa[L[from]]&&from!=0)
                    from=L[from];
                L[i]=from;
            }
        }
        R[t]=t+1;
        for(int i=t-1;i>=1;i--)
        {
            if(aa[i+1]>aa[i])
                R[i]=i+1;
            else
            {
                int from=i+1;
                while(aa[i]>=aa[R[from]]&&from!=t+1)
                    from=R[from];
                R[i]=from;
            }
        }
        bool flag=0;
        for(int i=1; i<=t; i++)
        {
            int res=-1;
            if(query(1,1,t,L[i],i)>res&&L[i]!=0)
                res=query(1,1,t,L[i],i);
            if(query(1,1,t,i,R[i])>res&&R[i]!=t+1)
                res=query(1,1,t,i,R[i]);
            if((res==-1&&aa[i]>=150000)||(aa[i]-res>=150000))
            {
                if(flag==0)
                {
                    printf("%d",i);
                    flag = 1;
                }
                else printf(" %d",i);
            }
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-11-10 10:52:31

UvaLive 6531 Go up the ultras的相关文章

UVALive 6531 Go up the ultras 单调栈+RMQ

题目链接:点击打开链接 题意: 给定n座山 下面n个数字表示n座山的高度 若这座山u合法,则要满足: 1.若u的左边存在比u高的山,设v是u左边距离u最近的且严格比u高的山,在[v,u]之间至少有一座山x,使得x和u的高度差>=15000 2.右边也同理. 同时满足1.2的情况则算合法. 问: 输出所有合法的山. 思路: 求距离某个点最近的山就是维护一个单调栈,然后给山的高度求一个RMQ. 写写写... #pragma comment(linker, "/STACK:1024000000,

LA 6531 Go up the Ultras 单调栈+RMQ

题意:已经懒得吐槽了..有N个山峰,(N<=10^5),每个山峰有高度h,对应着每个山峰有一个d值,每个山峰到所有其他的严格比 它高的山峰都会经过一个最低值(山谷),d代表是h减去这些最低值中的最大值的差(如果不存在比它高的山峰那么d就是它本身的 高度),问有多少山峰的d>=150000米. 思路:利用单调栈维护每个峰左边第一个比它高的峰的位置l,右边第一个比它高的峰的位置r,对于r,我们从前向后维护一个单调减 序列,如果当前考虑的点i比栈顶的元素高度高,那么弹出栈顶元素,并将它的r置为i,直

UVALive 4848 Tour Belt

F - Tour Belt Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 4848 Description Korea has many tourist attractions. One of them is an archipelago (Dadohae in Korean), a cluster of small islands sca

UVALive 6467 Strahler Order 拓扑排序

这题是今天下午BNU SUMMER TRAINING的C题 是队友给的解题思路,用拓扑排序然后就可以了 最后是3A 其中两次RE竟然是因为: scanf("%d",mm); ORZ 以后能用CIN还是CIN吧 QAQ 贴代码了: 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <iostre

UVALive 7077 Little Zu Chongzhi&#39;s Triangles (有序序列和三角形的关系)

这个题……我上来就给读错了,我以为最后是一个三角形,一条边可以由多个小棒组成,所以想到了状态压缩各种各样的东西,最后成功了……结果发现样例过不了,三条黑线就在我的脑袋上挂着,改正了以后我发现N非常小,想到了回溯每个棍的分组,最多分5组,结果发现超时了……最大是5^12 =  244,140,625,厉害呢…… 后来想贪心,首先想暴力出所有可能的组合,结果发现替换问题是一个难题……最后T T ,我就断片了.. 等看了别人的办法以后,我才发现我忽视了三角形的特性,和把数据排序以后的特点. 如果数据从

Gym 100299C &amp;&amp; UVaLive 6582 Magical GCD (暴力+数论)

题意:给出一个长度在 100 000 以内的正整数序列,大小不超过 10^ 12.求一个连续子序列,使得在所有的连续子序列中, 它们的GCD值乘以它们的长度最大. 析:暴力枚举右端点,然后在枚举左端点时,我们对gcd相同的只保留一个,那就是左端点最小的那个,只有这样才能保证是最大,然后删掉没用的. UVaLive上的数据有问题,比赛时怎么也交不过,后来去别的oj交就过了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&qu

UVALive 6511 Term Project

Term Project Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ID: 651164-bit integer IO format: %lld      Java class name: Main 解题:强连通分量 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1

UVALive 6508 Permutation Graphs

Permutation Graphs Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ID: 650864-bit integer IO format: %lld      Java class name: Main 解题:逆序数 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long l

UVALive 2659+HUST 1017+ZOJ 3209 (DLX

UVALive 2659 题目:16*16的数独.试了一发大白模板. /* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include