CodeForce 855B 暴力or线段树

Posted alking1001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForce 855B 暴力or线段树相关的知识,希望对你有一定的参考价值。

CodeForce 855B 暴力or线段树

题意

给你一串数,然后找出三个数,他们的前后关系和原来一样,可以相同,然后分别乘p,q,r,求他们积的和最大,并且输出这个数。

解题思路

  1. 这个可以使用线段树来做,找出区间内的最小值和最大值,如果x(代表pqr中的一个)小于零,就乘以这个区间的最小值,如果大于零,就乘以这个区间的最大值。然后\(j\)从1到n开始遍历。
  2. 或者可以暴力,不过这个暴力比一点重方法还要好,我看完就惊呆了,lxm大佬太强了。

代码实现

第一种:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<cmath>
# define ls (rt<<1)
# define rs (rt<<1|1)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f; //注意这里是8个3f,用来初始化用,很重要。
const int  maxn=1e5+7;
struct node
    int l, r;
    ll ma, mi;
t[maxn<<2];
ll num[maxn];
ll n, p, q, r;
void up(int rt)

    t[rt].ma=max(t[rt<<1].ma, t[rt<<1|1].ma);
    t[rt].mi=min(t[rt<<1].mi, t[rt<<1|1].mi);

void build(int rt, int l, int r)

    t[rt].l=l;
    t[rt].r=r;
    if(l==r)
    
        t[rt].ma=num[l];
        t[rt].mi=num[l];
        return ;
    
    int  mid=(l+r)>>1;
    build(ls, l, mid);
    build(rs, mid+1, r);
    up(rt);

ll query_ma(int rt, int l, int r)//寻找区间最大值

    if(l <= t[rt].l && t[rt].r <= r)
    
        return t[rt].ma;
    
    ll ans=-inf;
    int mid=(t[rt].l+t[rt].r)>>1;
    if(l<=mid) ans=max(ans, query_ma(ls, l, r));
    if(r>mid) ans=max(ans, query_ma(rs, l, r));
    return ans;

ll query_mi(int rt, int l, int r) //寻找区间最小值

    if(l <= t[rt].l && t[rt].r <= r)
    
        return t[rt].mi;
    
    ll ans=inf;
    int mid=(t[rt].l+t[rt].r)>>1;
    if(l<=mid) ans=min(ans, query_mi(ls, l, r));
    if(r>mid) ans=min(ans, query_mi(rs, l, r));
    return ans;

int main()

    while(scanf("%lld%lld%lld%lld", &n, &p, &q, &r)!=EOF)
    
        for(int i=1; i<=n; i++)
        
            scanf("%lld", &num[i]);
        
        build(1, 1, n);
        ll ans=-inf, tmp=0;
        for(int i=1; i<=n; i++) //遍历,这里的i就是题目中的j
        
            tmp=0;
            if(p<=0)
            
                tmp+=p*query_mi(1, 1, i);
            
            else tmp+=p*query_ma(1, 1, i);
            
            tmp+=q*num[i];
            
            if(r<=0)
            
                tmp+=r*query_mi(1, i, n);
            
            else tmp+=r*query_ma(1, i, n);
            
            ans=max(ans, tmp);
        
        printf("%lld\n", ans);
    
    return 0;

第二种:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll inf=0x3f3f3f3f3f3f3f3f;

int main()

    ll n, p, q, r, x;
    scanf("%lld%lld%lld%lld", &n, &p, &q, &r);
    ll m1=-inf, m2=-inf, m3=-inf;
    for(int i=1; i<=n; i++) //太巧妙了!
    
        scanf("%lld", &x);
        m1=max(m1, x*p);
        m2=max(m2, m1+x*q);
        m3=max(m3, m2+x*r); 
       
    printf("%lld\n", m3);
    return 0;
  

以上是关于CodeForce 855B 暴力or线段树的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5700 区间交 线段树暴力

P3372 模板线段树 1

5312: 冒险 线段树 复杂度分析

java,线段树

hdu 6430 线段树 暴力维护

POJ 1804 Brainman(5种解法,好题,暴力,归并排序,线段树单点更新,树状数组,平衡树)