CodeForce 855B 暴力or线段树
题意
给你一串数,然后找出三个数,他们的前后关系和原来一样,可以相同,然后分别乘p,q,r,求他们积的和最大,并且输出这个数。
解题思路
- 这个可以使用线段树来做,找出区间内的最小值和最大值,如果x(代表pqr中的一个)小于零,就乘以这个区间的最小值,如果大于零,就乘以这个区间的最大值。然后\(j\)从1到n开始遍历。
- 或者可以暴力,不过这个暴力比一点重方法还要好,我看完就惊呆了,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; }