zoukankan      html  css  js  c++  java
  • hdu 6406 Taotao Picks Apples (线段树)

    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 (1T10), the number of test cases.

    Each test case begins with a line of two integers n,m (1n,m105), denoting the number of apples and the number of queries. It is then followed by a single line of n integers h1,h2,,hn (1hi109), denoting the heights of the apples. The next m lines give the queries. Each of these m lines contains two integers p (1pn) and q (1q109), 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.
     
     

    Solution

    拿到题最开始想用前缀和维护答案,但是没有理清思路,后来就乱了。看到一篇大神的线段树直接维护答案的题解,简单理了一下思路

    对于线段树,维护区间最大值以及区间从左往右上升长度(即答案),我们注意到一个区间的答案=左区间答案数+右区间在左区间最大值基础上的贡献

    对于一个查询query(rt,v)表示将区间t之前的一个数改为v后的区间rt的对答案的贡献,

    rt->maxx<v直接返回0,总的区间最大值小于v,这个区间不可能贡献答案

    否则若rt->lson->maxx>v 此时只需关注左区间,因为右区间此时的贡献值和v不相关,注意这时的返回答案应该是tr[rt].cnt-tr[lson].cnt+query(lson,v),而不是tr[rson].cnt+query(lson,v)

    这两者是不等价的,因为一个cnt表示的是当前区间从左到右的上升长度,而tr[rson].cnt仅仅关注的是右区间,没有和整体直接挂钩

    再如果tr->lson->maxx<=v,此时左区间对答案无贡献,但右区间存在,查询右区间

    大概就是这样,线段树维护答案很灵活感觉,唉本人垃圾是想不到了

    贴一段大概理解之后写的ac代码吧


      1 #include <bits/stdc++.h>
      2 #define lson rt << 1
      3 #define rson rt << 1 | 1
      4 using namespace std;
      5 using ll = long long;
      6 using ull = unsigned long long;
      7 using pa = pair<int, int>;
      8 using ld = long double;
      9 int n, m, k;
     10 const int maxn = 1e5 + 10;
     11 const int mod = 998244353;
     12 int pre[maxn];
     13 template <class T>
     14 inline T read(T &ret)
     15 {
     16     int f = 1;
     17     ret = 0;
     18     char ch = getchar();
     19     while (!isdigit(ch))
     20     {
     21         if (ch == '-')
     22             f = -1;
     23         ch = getchar();
     24     }
     25     while (isdigit(ch))
     26     {
     27         ret = (ret << 1) + (ret << 3) + ch - '0';
     28         ch = getchar();
     29     }
     30     ret *= f;
     31     return ret;
     32 }
     33 template <class T>
     34 inline void write(T n)
     35 {
     36     if (n < 0)
     37     {
     38         putchar('-');
     39         n = -n;
     40     }
     41     if (n >= 10)
     42     {
     43         write(n / 10);
     44     }
     45     putchar(n % 10 + '0');
     46 }
     47 int a[maxn];
     48 struct node
     49 {
     50     int l, r, cnt, maxx;
     51 } tr[maxn << 2];
     52 int query(int rt, int v)
     53 {
     54     int l = tr[rt].l;
     55     int r = tr[rt].r;
     56     if (l == r)
     57         return tr[rt].maxx > v;
     58     if (tr[rt].maxx < v)
     59         return 0;
     60     int mid = l + r >> 1;
     61     if (tr[lson].maxx > v) //疑惑,为什么写出tr[rson].cnt+query(lson,v)答案不对
     62                            //啊左右区间和大区间并不相等,大区间=左区间+右区间贡献
     63         return tr[rt].cnt - tr[lson].cnt + query(lson, v);
     64     else
     65         return query(rson, v);
     66 }
     67 void pushup(int rt)
     68 {
     69     tr[rt].maxx = max(tr[lson].maxx, tr[rson].maxx);
     70     tr[rt].cnt = tr[lson].cnt + query(rson, tr[lson].maxx);
     71 }
     72 void build(int rt, int l, int r)
     73 {
     74     tr[rt].l = l;
     75     tr[rt].r = r;
     76     if (l == r)
     77     {
     78         tr[rt].cnt = 1;
     79         tr[rt].maxx = a[l];
     80         return;
     81     }
     82     int mid = l + r >> 1;
     83     build(lson, l, mid);
     84     build(rson, mid + 1, r);
     85     pushup(rt);
     86 }
     87 void update(int rt, int L, int v)
     88 {
     89     int l = tr[rt].l;
     90     int r = tr[rt].r;
     91     if (l == r && l == L)
     92     {
     93         tr[rt].maxx = v;
     94         return;
     95     }
     96     int mid = l + r >> 1;
     97     if (L <= mid)
     98         update(lson, L, v);
     99     else
    100         update(rson, L, v);
    101     pushup(rt);
    102 }
    103 int main(int argc, char const *argv[])
    104 {
    105     ios::sync_with_stdio(false);
    106     cin.tie(0);
    107     cout.tie(0);
    108     int t;
    109     cin >> t;
    110     while (t--)
    111     {
    112         cin >> n >> m;
    113         for (int i = 1; i <= n; i++)
    114             cin >> a[i];
    115         build(1, 1, n);
    116         while (m--)
    117         {
    118             int p, q;
    119             cin >> p >> q;
    120             update(1, p, q);
    121             cout << tr[1].cnt << "
    ";
    122             update(1, p, a[p]);
    123         }
    124     }
    125     return 0;
    126 }
    View Code
  • 相关阅读:
    667. Beautiful Arrangement II
    695. Max Area of Island
    485. Max Consecutive Ones
    coedforces #481Div(3)(ABCDEFG)
    躲藏
    车辆问题(贪心)
    最小化代价(优先队列)
    PUBG
    hdu 2647 Reward(拓扑排序+优先队列)
    HDU 3342 Legal or Not(判断环)
  • 原文地址:https://www.cnblogs.com/mooleetzi/p/11287982.html
Copyright © 2011-2022 走看看