J. Taotao Picks Apples(st&二分)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了J. Taotao Picks Apples(st&二分)相关的知识,希望对你有一定的参考价值。
J. Taotao Picks Apples(st&二分)
1.ST表+二分+单调队列
考虑预处理出 d p 1 ( i ) dp_1(i) dp1(i) 表示对于序列 [ 1 , i ] [1,i] [1,i] 从 1 1 1出发的最大值。
然后用 S T ST ST表维护区间的最大值。
再用单调队列维护从某个位置开始的后缀最大长度 d p 2 ( i ) dp_2(i) dp2(i)。
这样对于一个询问 ( x , k ) (x,k) (x,k)
初始化 a n s = d p 1 ( x − 1 ) ans=dp_1(x-1) ans=dp1(x−1)
若 k > m x = m a x ( a i ) , i ∈ [ 1 , x − 1 ] k>mx=max(a_i),i\\in[1,x-1] k>mx=max(ai),i∈[1,x−1]
则 a n s + 1 ans+1 ans+1。
然后找到后缀第一个大于 m a x ( k , m x ) max(k,mx) max(k,mx)的位置 p o s pos pos。
a n s = a n s + d p 2 ( p o s ) ans=ans+dp_2(pos) ans=ans+dp2(pos) 就是答案。
时间复杂度: O ( n + q l o g n ) O(n+qlogn) O(n+qlogn)
静态区间最值还可用线段树,不写了。
后缀最大长还可以用单调栈维护(向右查找第一个大于它的位置)
参考代码
const int maxn = 1e5+5;
int a[maxn];
int dp1[maxn], dp2[maxn];
void read(int &x)
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
int dp[maxn][20];
int n, m;
void rmq()
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<(j-1))<=n;i++)
dp[i][j]=max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
int get_ma(int l, int r)
int k = 0; if (l > r) return 0;
while((1<<(k+1))<=r-l+1)k++;
return max(dp[l][k] ,dp[r-(1<<k)+1][k]);
int Find(int l, int r, int x)
int ans = -1;
while(l <= r)
int mid = (l + r) >> 1;
int tmp = get_ma(l, mid);
if (tmp > x)
ans = mid;
r = mid - 1;
else l = mid + 1;
return ans;
int que[maxn], cnt[maxn];
void solve()
read(n); read(m);
int mx = 0;
for(int i = 1 ; i <= n ; i ++)
read(a[i]); dp[i][0] = a[i];
if (a[i] > mx)
dp1[i] = dp1[i-1] + 1;
mx = a[i];
else dp1[i] = dp1[i-1];
cnt[i] = mx;
rmq();
int tail = 0, head = 1;
for (int i = n ; i >= 1 ; i --)
while(head <= tail && que[tail] <= a[i]) --tail;
que[++tail] = a[i];
dp2[i] = (tail - head + 1);
// cnt[i] 表示i位置前面最大数是多少, dp1[i]表示前缀的答案, dp2是后缀处理的答案.
while(m--)
int l, r;
read(l); read(r);
int ans = dp1[l-1]; // 前面是具有可推性质的!!!
if (r > cnt[l-1]) ++ ans;
r = max(r, cnt[l-1]);
int pos = Find(l+1, n, r);
if (pos != -1) ans += dp2[pos];
printf("%d\\n", ans);
以上是关于J. Taotao Picks Apples(st&二分)的主要内容,如果未能解决你的问题,请参考以下文章
hdu6406 Taotao Picks Apples 多校第8场1010
hdu 6406 Taotao Picks Apples 线段树 单点更新
HDU暑假多校第八场J-Taotao Picks Apples
hdu 6406 Taotao Picks Apples 锛?018 Multi-University Training Contest 8 1010锛夛紙浜屽垎锛屽墠缂€鍜岋級