码迷,mamicode.com
首页 > 其他好文 > 详细

北京清北 综合强化班 Day4 T1

时间:2017-10-05 20:55:59      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:单调队列   接下来   cst   mit   show   mat   using   def   stream   

财富(treasure)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK有n个小伙伴。每个小伙伴有一个身高hi。

这个游戏是这样的,LYK生活的环境是以身高为美的环境,因此在这里的每个人都羡慕比自己身高高的人,而每个人都有一个属性ai表示它对身高的羡慕值。

这n个小伙伴站成一列,我们用hi来表示它的身高,用ai来表示它的财富。

每个人向它的两边望去,在左边找到一个最近的比自己高的人,然后将ai朵玫瑰给那个人,在右边也找到一个最近的比自己高的人,再将ai朵玫瑰给那个人。当然如果没有比自己身高高的人就不需要赠送别人玫瑰了。也就是说一个人会给0,1,2个人玫瑰(这取决于两边是否有比自己高的人)。

每个人都会得到若干朵玫瑰(可能是0朵),LYK想知道得了最多的玫瑰的那个人得了多少玫瑰。(然后嫁给他>3<)

输入格式(treasure.in)

    第一行一个数n表示有n个人。

    接下来n行,每行两个数hi,ai。

输出格式(treasure.out)

    一个数表示答案。

输入样例

3

4 7

3 5

6 10

输出样例

12

样例解释

第一个人会收到5朵玫瑰,第二个没人送他玫瑰,第三个人会收到12朵玫瑰。

数据范围

对于50%的数据n<=1000,hi<=1000000000。

对于另外20%的数据n<=50000,hi<=10。

对于100%的数据1<=n<=50000,1<=hi<=1000000000。1<=ai<=10000。

思路:

  1.首先这题暴力可过。。。

  2.std:每个点向左找一个最近的且比它大的,向右找最近且比向右找最近且比它大的它大的从右往左枚举过来

for (int i=n; i>=1; i--)
{
    while (r && s[r]<=h[i]) r--;
    b[q[r]]+=a[i];
    s[++r]=h[i]; q[r]=i;
}
//b[i]第i个人收到的玫瑰数
//q[i]在单调的数列中第i个位置是n个人中的哪个人

   求最靠近它且比它高的那个位置是哪个

  3.My

    正着跑一边单调队列(单调下降),然后倒着跑一遍,每次更新就判断一下队尾元素是否后面的人被更新,如果没有:先让想加入的这个点i的ans加上队尾元素的a值,然后标记

    最后把ans数组sort一遍,输出ans[n]即可

上代码:

技术分享
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> 
#define LL long long
using namespace std;

const int M = 50055;
int n,qt,a[M];
LL h[M],q1[M],q2[M],ans[M];
bool visq[M];

int main() {
    freopen("treasure.in","r",stdin);
    freopen("treasure.out","w",stdout);
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) {
        scanf("%d%d",&h[i],&a[i]);
        while(qt>0 && h[i]>q1[qt]) { //right 
            if(!visq[q2[qt]]) {
                ans[i]+=a[q2[qt]];
                visq[q2[qt]]=true;
            }
            qt--;
        }
        q1[++qt]=h[i];
        q2[qt]=i; 
    }
    qt=0;
    memset(visq,0,sizeof(visq)); memset(q1,0,sizeof(q1)); memset(q2,0,sizeof(q2));
    for(int i=n; i>=1; --i) { //left
        while(qt>0 && h[i]>q1[qt]) { //right 
            if(!visq[q2[qt]]) {
                ans[i]+=a[q2[qt]];
                visq[q2[qt]]=true;
            }
            qt--;
        }
        q1[++qt]=h[i];
        q2[qt]=i; 
    }
    sort(ans+1,ans+n+1);
    printf("%d",ans[n]);
    return 0;
}
My
技术分享
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int n,s[50002],d[50002],ans[50002],ANS,a[50002],b[50002],r,i;
int main()
{
    freopen("treasure.in","r",stdin);
    freopen("treasure.out","w",stdout);
    cin>>n;
    for (i=1; i<=n; i++) scanf("%d%d",&a[i],&b[i]);
    s[1]=a[1]; d[1]=1; r=1;
    for (i=2; i<=n; i++)
    {
        while (r!=0 && a[i]>s[r]) { ans[i]+=b[d[r]]; r--; }
        r++;
        s[r]=a[i];
        d[r]=i;
    }
    s[1]=a[n]; d[1]=n; r=1;
    for (i=n-1; i>=1; i--)
    {
        while (r!=0 && a[i]>s[r]) { ans[i]+=b[d[r]]; r--; }
        r++;
        s[r]=a[i];
        d[r]=i;
    }
    for (i=1; i<=n; i++) ANS=max(ANS,ans[i]);
    cout<<ANS;
    return 0;
}
std

北京清北 综合强化班 Day4 T1

标签:单调队列   接下来   cst   mit   show   mat   using   def   stream   

原文地址:http://www.cnblogs.com/zxqxwnngztxx/p/7625660.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!