zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", m3);
    	return 0;
     } 
    
    欢迎评论交流!
  • 相关阅读:
    json初接触
    background-position,有逗号和没逗号:截然不同的结果
    事件委托(事件代理)
    OAuth 2.0
    indexedDB为何物
    你不能阻止DOM
    PWA需要的技术
    const 和let的本质区别
    判断一个类是否继承了另外一个类的方法
    spawn函数的实现(前文自动执行器的翻版)
  • 原文地址:https://www.cnblogs.com/alking1001/p/11405848.html
Copyright © 2011-2022 走看看