区间的价值
Accepts: 0
Submissions: 0
Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
我们定义“区间的价值”为一段区间的最大值*最小值。
一个区间左端点在LLL,右端点在RRR,那么该区间的长度为(R−L+1)(R-L+1)(R−L+1)。
现在聪明的杰西想要知道,对于长度为kkk的区间,最大价值的区间价值是多少。
当然,由于这个问题过于简单。
我们肯定得加强一下。
我们想要知道的是,对于长度为1∼n1\sim n1∼n的区间,最大价值的区间价值分别是多少。
样例解释:
长度为111的最优区间为2−22-22−2 答案为6∗66*66∗6
长度为222的最优区间为4−54-54−5 答案为4∗44*44∗4
长度为333的最优区间为2−42-42−4 答案为2∗62*62∗6
长度为444的最优区间为2−52-52−5 答案为2∗62*62∗6
长度为5的最优区间为1−51-51−5 答案为1∗61*61∗6
Input
多组测试数据
第一行一个数n(1≤n≤100000)n(1\leq n\leq 100000)n(1≤n≤100000)。
第二行nnn个正整数(1≤ai≤109)(1\leq a_{i}\leq 10^{9})(1≤a?i??≤10?9??),下标从111开始。
由于某种不可抗力,aia_{i}a?i??的值将会是1∼1091\sim 10^{9}1∼10?9??内随机产生的一个数。(除了样例)
Output
输出共nnn行,第iii行表示区间长度为iii的区间中最大的区间价值。
Sample Input
5 1 6 2 4 4
Sample Output
36 16 12 12 6 题解,构造两个线段树,分别求出最大与最小的坐标。然后利用用一个类似快排的方法,每次找到最大最小后,更新所有包含该区间的区间的值,然后选择最小的下标作为分割点,继续递归划分。为什么选最小坐标呢?因为我们最后求的是最大区间价值,所以要以最小下标作为分割点(分割点之后是不会进行计算的),同时不断缩短区间,不断更新。
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 100010; int MAX[maxn<<2]; int MIN[maxn<<2]; long long ans[maxn]; long long N[maxn]; int Pos=0,n; long long read() { long long ans=0; char last=‘ ‘,ch=getchar(); while(ch<‘0‘ || ch>‘9‘)last=ch,ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘)ans=ans*10+ch-‘0‘,ch=getchar(); if(last==‘-‘)ans=-ans; return ans; } void PushUP_max(int rt) { if (N[MAX[rt<<1]] > N[MAX[rt<<1|1]]) MAX[rt] = MAX[rt<<1] ; else MAX[rt] =MAX[rt<<1|1]; } void PushUP_min(int rt) { if (N[MIN[rt<<1]] < N[MIN[rt<<1|1]]) MIN[rt] = MIN[rt<<1] ; else MIN[rt] =MIN[rt<<1|1]; } void build_max(int l,int r,int rt) { if (l == r) { MAX[rt]=++Pos; return ; } int m = (l + r) >> 1; build_max(lson); build_max(rson); PushUP_max(rt); } void build_min(int l,int r,int rt) { if (l == r) { MIN[rt]=MAX[rt]; return ; } int m = (l + r) >> 1; build_min(lson); build_min(rson); PushUP_min(rt); } int query_max(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return MAX[rt]; } int m = (l + r) >> 1; int ret=0; N[0]=0; if (L <= m) { int tl=query_max(L , R , lson); if (N[tl]>N[ret]) ret = tl; } if (R > m) { int tr=query_max(L , R , rson); if (N[tr]>N[ret])ret = tr; } return ret; } int query_min(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return MIN[rt]; } int m = (l + r) >> 1; int ret =0; N[0]=999999999; if (L <= m) { int tl=query_min(L , R , lson); if (N[tl]<N[ret]) ret = tl; } if (R > m) { int tr=query_min(L , R , rson); if (N[tr]<N[ret])ret = tr; } return ret; } void sovle(int l,int r) { if (l>r) return ; int max_p=query_max(l , r , 1 , n , 1); int min_p=query_min(l , r , 1 , n , 1); long long num=N[max_p]*N[min_p]; int nl,nr; if(max_p>min_p) { nl=min_p; nr=max_p; } else { nr=min_p; nl=max_p; } for (int i=nr-nl+1; i<=r-l+1; i++) ans[i]=max(ans[i],num); sovle(l,min_p-1); sovle(min_p+1,r); } int main() { while(~scanf("%d",&n)) { getchar(); memset(ans,0,sizeof(ans)); for (int i=1; i<=n; i++) N[i]=read(); Pos=0; build_max(1 , n , 1); build_min(1 , n , 1); sovle(1,n); for (int i=1; i<=n; i++) printf("%I64d\n",ans[i]); } return 0; }
时间: 2024-10-12 12:54:12