HDU 5696 RMQ+滑窗

区间的价值

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 844    Accepted Submission(s): 398

Problem Description

我们定义“区间的价值”为一段区间的最大值*最小值。

一个区间左端点在L

,右端点在R

,那么该区间的长度为(R−L+1)

现在聪明的杰西想要知道,对于长度为k

的区间,最大价值的区间价值是多少。

当然,由于这个问题过于简单。

我们肯定得加强一下。

我们想要知道的是,对于长度为1∼n

的区间,最大价值的区间价值分别是多少。

样例解释:

长度为1

的最优区间为2−2

答案为6∗6

长度为2

的最优区间为4−5

答案为4∗4

长度为3

的最优区间为2−4

答案为2∗6

长度为4

的最优区间为2−5

答案为2∗6

长度为5的最优区间为1−5

答案为1∗6

Input

多组测试数据

第一行一个数n(1≤n≤100000)

第二行n

个正整数(1≤ai≤109)

,下标从1

开始。

由于某种不可抗力,ai

的值将会是1∼109

内<b style="color:red;">随机产生</b>的一个数。(除了样例)

Output

输出共n

行,第i

行表示区间长度为i

的区间中最大的区间价值。

Sample Input

5

1 6 2 4 4

Sample Output

36

16

12

12

6

Source

2016"百度之星" - 初赛(Astar Round2B)

题意:中文题面  求长度为i 的区间中最大的区间价值。区间价值=区间最小值*区间最大值

题解:1.RMQ 记录每个区间的最大值

2.滑窗处理以a[i]为最小值的左右边界

3.那么对于 一个答案 a[i]*rmq(l[i],r[i]) 为此长度的答案,我们可以发现他是可以更新到小于其长度的所有长度答案的

 1 #include<bits/stdc++.h>
 2 #define ll __int64
 3 using namespace std;
 4 ll f[100005][50];
 5 ll a[100005];
 6 ll l[100005];
 7 ll r[100005];
 8 ll n;
 9 ll ans[100005];
10 ll aa[100005];
11 void rmq_init()
12 {
13     for(int j=1;(1<<j)<=n;j++)
14     for(int i=1;i+(1<<(j))-1<=n;i++)
15     {
16       f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
17     }
18 }
19 int rmq(ll aa,ll bb)
20 {
21     ll k=0;
22     ll ans1;
23     while((1<<(k+1))<=bb-aa+1)
24     k++;
25     ans1=max(f[aa][k],f[bb-(1<<k)+1][k]);
26     return ans1;
27 }
28
29 int main()
30 {
31     while(scanf("%I64d",&n)!=EOF)
32    {
33      for(int i=1;i<=n;i++)
34     {
35         scanf("%I64d",&a[i]);
36         f[i][0]=a[i];
37     }
38     rmq_init();
39     a[0]=-1;
40     a[n+1]=-1;
41     l[1]=1;
42     for(int i=2;i<=n;i++)
43     {
44         int temp=i-1;
45         while(a[temp]>=a[i])
46             temp=l[temp]-1;
47         l[i]=temp+1;
48     }
49     r[n]=n;
50     for(int i=n-1;i>=1;i--)
51     {
52        int temp=i+1;
53        while(a[temp]>=a[i])
54           temp=r[temp]+1;
55        r[i]=temp-1;
56     }
57     memset(ans,0,sizeof(ans));
58     memset(aa,0,sizeof(aa));
59      for(int i=1;i<=n;i++)
60      {
61         ll mm=rmq(l[i],r[i]);
62         ans[r[i]-l[i]+1]=max(ans[r[i]-l[i]+1],mm*a[i]);
63      }
64      for(int i=n;i>=1;i--)
65         aa[i]=max(ans[i],aa[i+1]);
66      for(int i=1;i<=n;i++)
67        printf("%I64d\n",aa[i]);
68    }
69     return 0;
70 }
时间: 2024-09-30 06:08:15

HDU 5696 RMQ+滑窗的相关文章

HDU 5247 找连续数(RMQ+滑窗)

找连续数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 281    Accepted Submission(s): 102 Problem Description 小度熊拿到了一个无序的数组,对于这个数组,小度熊想知道是否能找到一个k 的区间,里面的 k 个数字排完序后是连续的. 现在小度熊增加题目难度,他不想知道是否有这样的 k

[poj 3261]后缀数组+滑窗最小值

题目链接:http://poj.org/problem?id=3261 这个是可以交叉的重复串,所以用height就可以了,但是题目说让重复k次以上,也就是直接做一个k-1长度的滑窗最小值,从这些最小值里取最大即可. 这里其实为了节省空间可以先给数字离散化一下,这样就只有20000了,不过不离散化空间也够用. #include<cstdio> #include<algorithm> #include<cstring> #include<queue> usin

Codeforces 526 E Transmitting Levels 滑窗(two points) + 枚举

题意:给你一个环形数组,让你求将这个数组分成 每段和 <= k 的最小段数. 解题思路:滑窗求的以 i结尾的 最长段长度,然后枚举最小的那个段长度中的值为终点搜索(因为必定有一个分割点在 最小段长上) 解题代码: 1 // File Name: e.cpp 2 // Author: darkdream 3 // Created Time: 2015年04月05日 星期日 14时55分31秒 4 5 #include<vector> 6 #include<list> 7 #in

UVA 1619/POJ2796 滑窗算法/维护一个单调栈

Feel Good Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12409   Accepted: 3484 Case Time Limit: 1000MS   Special Judge Description Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated

集训第四周(高效算法设计)K题 (滑窗问题)

UVA 11572 唯一的雪花 题意:给你从1到n的数组,要求求得其中的最长连续不重复子序列,经典的滑窗问题,方法是维护一个窗口,设置左框和右框,然后不断的进行维护和更新 方法一: #include"iostream" #include"set" #include"cstring" #include"cstdio" #include"algorithm" using namespace std; const

滑窗模板_双向队列

附上电科算法讲堂  https://www.bilibili.com/video/av23189029?t=641  (感谢那些讲课的美好的人们) /* * 注: 还有少许细节问题可能需要注意: 例如 总长度小于窗口长度的情况. * 和rGetMax rGetMin 下标小于零的情况 没有pass.. */ class HuaChuang_Max { public: struct cnobe { int id; int val; cnobe () {} cnobe (int _id, int _

【10.7校内测试】【队列滑窗】【2-sat】【贪心+栈二分+线段树(noip模拟好题)】【生日祭!】

比较好想的一道题,直接用队列滑窗,因为扫一遍往队列里加东西时,改变的只有一个值,开桶储存好就行了! #include<bits/stdc++.h> using namespace std; int n, k, r; inline int min(int a, int b) { return a > b ? b : a; } inline int max(int a, int b) { return a > b ? a : b; } int sum[200005], q[200005

The Preliminary Contest for ICPC Asia Shanghai 2019 G. Substring (滑窗+哈希)

G. Substring 哎 一直超时or超内存 然后一直改一直改 然后 是 答案错误 然后 然后 最后结论是哈希姿势不对 我在别的地方找了这个: //https://www.cnblogs.com/napoleon_liu/archive/2010/12/29/1920839.html uint32_t hash( uint32_t a) { a = (a+0x7ed55d16) + (a<<12); a = (a^0xc761c23c) ^ (a>>19); a = (a+0x

hdu 5696 区间的价值 单调栈+rmq

区间的价值 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description 我们定义“区间的价值”为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少. 当然,由于这个问题过于简单. 我们肯定得加强一下. 我们想要知道的是,对于长度为1∼n