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(x1)

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,x1]

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锛夛紙浜屽垎锛屽墠缂€鍜岋級

多校寒训TaoTao要吃鸡dp(未完成)

taotao商城遇到的问题