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

    Taotao Picks Apples

    题目传送门

    解题思路

    建立一颗线段树,维护当前区间内的最大值maxx和可摘取的苹果数num。最大值很容易维护,主要是可摘取的苹果数怎么合并。合并左右孩子时,左孩子里可摘取苹果必然还是可以摘取,所以我们讨论右孩子。
    如果右孩子的最大值小于左孩子,根据题目条件,右孩子里的苹果都不能摘取了,合并结果就是左孩子的数量,如果右孩子的最大值大于左孩子,那么右孩子里存在可以摘取的苹果,接下来就是一个递归的过程,假设右孩子为t,左孩子的最大值为k,如果t->lchild->maxx < k, 那么t->lchild中不存在可摘取的苹果,递归t->rchild求t->rchild中的数量,如果t->lchild->maxx > k,那么t->lchild和t->rchild中都存在可摘取的苹果,而此时t->rchild已经不受k的影响了,只受t->lchild->maxx的影响,所以可以直接加上t->rchild->num,再加上递归求出的t->lchild中的数量。

    代码如下

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    
    inline int read(){
        int res = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            res = (res << 3) + (res << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -res : res;
    }
    
    const int N = 100005;
    int v[N];
    struct node{
        int l, r;
        int maxx, num;
    }tree[N << 2];
    
    int get(int k, int x)  //递归过程
    {
        if(tree[k].num == 1){
            return tree[k].maxx > x;
        }
        if(tree[2*k].maxx > x)
            return get(2*k, x) + (tree[k].num - tree[2*k].num);
        else if(tree[2*k].maxx == x)
            return tree[k].num - tree[2*k].num;
        else
            return get(2*k+1, x);
    }
    
    void pushup(int k)  //合并
    {
        tree[k].maxx = max(tree[2*k].maxx, tree[2*k+1].maxx);
        tree[k].num = tree[2*k].num;
        if(tree[2*k+1].maxx > tree[2*k].maxx)
            tree[k].num += get(2*k+1, tree[2*k].maxx);  
    }
    
    void build(int k, int l, int r)
    {
        tree[k].l = l, tree[k].r = r;
        if(l == r){
            tree[k].maxx = v[l];
            tree[k].num = 1;
            return;
        }
        int mid = (l + r) / 2;
        build(2*k, l, mid);
        build(2*k+1, mid+1, r);
        pushup(k);
    }
    
    void update(int k, int p, int q)
    {
        if(tree[k].l == tree[k].r){
            tree[k].maxx = q;
            return;
        }
        int mid = (tree[k].l + tree[k].r) / 2;
        if(p <= mid)
            update(2*k, p, q);
        else
            update(2*k+1, p, q);
        pushup(k);
    }
    
    inline int query()
    {
        return tree[1].num;
    }
    
    int main()
    {
        int t;
        cin >> t;
        while(t --){
            int n, m;
            n = read(), m = read();
            for(int i = 1; i <= n; i ++)
                v[i] = read();
            build(1, 1, n);
            for(int i = 1; i <= m; i ++){
                int p, q;
                p = read(), q = read();
                update(1, p, q);
                printf("%d
    ", query());
                update(1, p, v[p]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    统计学习方法学习笔记第二章(感知机)
    filebeat句柄占用问题
    小组年终总结的汇总
    使用docker制作zookeeper镜像
    普罗米修斯在k8s上面的部署
    k8s亲和性和反亲和性的理解
    AlertManager 的在k8s集群上面的安装部署使用
    filebeat生产上面镜像制作的流程
    普罗米修斯生产上面的性能优化点
    AlertManger集群的搭建
  • 原文地址:https://www.cnblogs.com/whisperlzw/p/11211524.html
Copyright © 2011-2022 走看看