HDU 6406 Taotao Picks Apples [ 线段树 + DP ]

7 篇文章 0 订阅
3 篇文章 0 订阅

题目链接:

2018 Multi-University Training Contest 8 Taotao Picks Apples HDU - 6406

题意概括:

按顺序给出一些苹果的高度,只有当前苹果是第一个或者高度严格大于前一个时才会被摘。现在给出一些独立的询问,一次询问把位置 p 的高度改为 q , 问改变后可以摘几个苹果。

数据范围:

1\leq T\leq 10 , 1\leq n,m\leq 10^{5}1\leq h_{i}\leq 10^{9}

1\leq p\leq n1\leq q\leq 10^{9}

题解分析:

这道题看似是求 LIS,仔细看题后发现不是。LIS 有一种决策性,对当前可选的点,需要进行决策看是否要选。而这题显然有一种强制性,就是若当前点可以选,则一定要选。

这里可以用 DP 维护两个数组。pre[i] 记录的是从 1 到 i 所摘的苹果个数,back[i] 数组记录的是从 i 到 n 位置可以摘的苹果个数。由于区间内第一个苹果一定要摘,接着向后找更高的苹果,因此最后摘的苹果一定是该区间内最高的。当把 p 高度改为 q 之后,找出区间 1 至 p-1 内最高的位置 pos,ans = pre[pos],若 q > h[pos],则 ans++。再找出 p+1 至 n 区间内,第一个高度大于max(q, h[pos]) 的位置 pos2,ans += back[pos2]。别忘了考虑当 p 为 1 或 n 这些极端情况的特判。

由于询问的次数很多,数据结构采用线段树,树中存储的是该区间内的最大值。维护两个询问:

  • 查询区间内的最大值位置 pos
  • 查询区间内第一个值大于 v 的点位置 pos2

其中,back 数组的 DP 可以用到第二个查询函数。

AC代码:

#include <stdio.h>
#include <memory.h>
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define min(a,b)    (((a) < (b)) ? (a) : (b))
using namespace std;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;

int origin[MAXN], tree[MAXN<<2], pre[MAXN], back[MAXN], pos;

void pushup(int p) {
    tree[p]= max(tree[p << 1], tree[p << 1 | 1]);
}

void build(int p, int l, int r) {      //线段树中存的是当前线段的最大值
    if (l == r) {
        tree[p] = origin[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    pushup(p);
}

void query_max(int p, int l, int r, int ql, int qr) {       //找到当前区间的最大值的pos位置
    if (l == r) {
        if (origin[pos] < tree[p]) pos = l;
        return;
    }
    int mid = (l + r) >> 1;
    if (ql <= l && r <= qr) {
        if (tree[p << 1] >= tree[p << 1 | 1]) query_max(p << 1, l, mid, ql, qr);
        else query_max(p << 1 | 1, mid + 1, r, ql, qr);
        return;
    }
    if (qr > mid) query_max(p << 1 | 1, mid + 1, r, ql, qr);
    if (ql <= mid) query_max(p << 1, l, mid, ql, qr);
}

void query_first(int p, int l, int r, int ql, int qr, int v) {      //找到第一个严格大于的数的pos。若没找到,则不改变pos值
    if (l == r) {
        pos = min(pos, l);
        return;
    }
    int mid = (l + r) >> 1;
    if (ql <= l && r <= qr) {
        if (tree[p << 1] > v)  query_first(p << 1, l, mid, ql, qr, v);
        else if (tree[p << 1 | 1] > v) query_first(p << 1 | 1, mid + 1, r, ql, qr, v);
        return;
    }
    if (qr > mid && tree[p << 1 | 1] > v)  query_first(p << 1 | 1, mid + 1, r, ql, qr, v);
    if (ql <= mid && tree[p << 1] > v)  query_first(p << 1, l, mid, ql, qr, v);
}


int main () {
    int T;
    scanf("%d", &T);
    while (T --) {
        int n, m, max = -1;
        scanf("%d%d", &n, &m);

        for (int i = 1; i <= n; i ++) {
            scanf("%d", origin + i);
            if (origin[i] > max) {pre[i] = pre[i - 1] + 1; max = origin[i];}
            else pre[i] = pre[i - 1];
        }

        build(1, 1, n);

        for (int i = n; i >= 1; i --) {
            pos = INF;
            query_first(1, 1, n, i, n, origin[i]);
            if (pos != INF)           //pos的值改变,说明找到了合适的值
                back[i] = back[pos] + 1;
            else
                back[i] = 1;
        }

        int p, q, ans;
        while (m --) {
            scanf("%d%d", &p, &q);
            ans = pos = 1;            //防止 pos = INF 时溢出
            if (p != 1) {
            query_max(1, 1, n, 1, p - 1);
            ans = pre[pos];
            if (q > origin[pos]) ans ++;
            else q = origin[pos];     //只有q不是第一位时才需要根据大小变化。因为若为首位,肯定要选改变后的q值
            }

            pos = INF;
            if (p != n)
            query_first(1, 1, n, p + 1, n, q);
            if (pos != INF)
            ans += back[pos];

            printf("%d\n", ans);
        }
    }
}

 

                                                   Taotao Picks Apples

                           Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Problem Description

There is an apple tree in front of Taotao's house. When autumn comes, n apples on the tree ripen, and Taotao will go to pick these apples.
When Taotao picks apples, Taotao scans these apples from the first one to the last one. If the current apple is the first apple, or it is strictly higher than the previously picked one, then Taotao will pick this apple; otherwise, he will not pick.
Given the heights of these apples h1,h2,⋯,hn, you are required to answer some independent queries. Each query is two integers p,q, which asks the number of apples Taotao would pick, if the height of the p-th apple were q (instead of hp). Can you answer all these queries?

Input

The first line of input is a single line of integer T (1≤T≤10), the number of test cases.
Each test case begins with a line of two integers n,m (1≤n,m≤10^{5}), denoting the number of apples and the number of queries. It is then followed by a single line of n integers h1,h2,⋯,hn (1≤hi≤10^{9}), denoting the heights of the apples. The next m lines give the queries. Each of these m lines contains two integers p (1≤p≤n) and q (1≤q≤10^{9}), as described in the problem statement.

Output

For each query, display the answer in a single line.

Sample Input

1
5 3
1 2 3 4 4
1 5
5 5
2 3

Sample Output

1
5
3

Hint

For the first query, the heights of the apples were 5, 2, 3, 4, 4, so Taotao would only pick the first apple.
For the second query, the heights of the apples were 1, 2, 3, 4, 5, so Taotao would pick all these five apples.
For the third query, the heights of the apples were 1, 3, 3, 4, 4, so Taotao would pick the first, the second and the fourth apples.

Source

2018 Multi-University Training Contest 8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值