hdu 6406 Taotao Picks Apples 线段树 单点更新

Taotao Picks Apples

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2506    Accepted Submission(s): 786

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≤105), 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≤109), 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≤109), as described in the problem statement.

Output

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

给你长度为n的序列, 然后从位置1,寻找单调栈的最大长度

然后修改 v[pos] = val, 再求 单调栈的最大长度

但是队友说是单调栈 ,我就用线段树维护了个单调栈,但是我维护的好像有些SB,就是每次左区间的最大值+(用单调栈跑一次最大长度)

然后完美的T了 ,然后就没管这道题了

后来看了一个人的题解,是这样子分析的

对于每一个区间, 贡献只能从左区间  + 右区间的部分选择

然后 考虑: 两种情况 ,如果 右区间的最大值 <= 左区间最大值,那么右区间肯定没有贡献,为0

然后考虑 :如果右区间的最大值 >  左区间最大值,那么问题可以递归 右区间的左儿子 和 右儿子的情况

这样的复杂度 大概是T*m*logn*logn (单点更新val值一个log  然后每次 合并区间的时候又要一个log)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
#define ls rt<<1
#define rs rt<<1|1

int mx[N<<2],cnt[N<<2];

int query(int rt,int l,int r,int v) {
    if(l==r) return mx[rt] > v;
    if(mx[rt] <= v) return 0;
    int m = (l+r)>>1;
    if(mx[ls] <= v) return query(rs,m+1,r,v);
    else return cnt[rt]-cnt[ls]+query(ls,l,m,v);
}
int n,m,v[N];
void build(int rt,int l,int r) {
    mx[rt] = cnt[rt] =0;
    if(l == r) {
        mx[rt]=v[l]; cnt[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(ls,l,m);
    build(rs,m+1,r);
    mx[rt]=max(mx[ls], mx[rs]);
    cnt[rt] = cnt[ls] + query(rs,m+1,r,mx[ls]);
}

void update(int rt,int l,int r,int pos,int val) {
    if(l==r && l == pos) {
        mx[rt]=val;
        cnt[rt] = 1;
        return ;
    }
    int m = (l+r)>>1;
    if(pos <= m)
        update(ls,l,m,pos,val);
    else
        update(rs,m+1,r,pos,val);
    mx[rt]=max(mx[ls], mx[rs]);
    cnt[rt] = cnt[ls] + query(rs,m+1,r,mx[ls]);
}

int main() {
    //freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    while (T--) {
        scanf("%d %d", &n, &m);
        for(int i=1;i<=n;i++)
            scanf("%d",&v[i]);
        build(1,1,n);
        while (m--) {
            int pos, val;
            scanf("%d %d",&pos,&val);
            //pos位置 更新成val
            update(1,1,n,pos,val);
            printf("%d\n",cnt[1]);
            //还原
            update(1,1,n,pos,v[pos]);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Draymonder/p/9535550.html

时间: 2024-10-02 20:32:00

hdu 6406 Taotao Picks Apples 线段树 单点更新的相关文章

hdu 1754 I Hate It 线段树单点更新和区间求和

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 参照HH大牛写的额! Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多

HDU 1166 敌兵布阵(线段树单点更新,板子题)

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 87684    Accepted Submission(s): 36912 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务

HDU 1754 I Hate It 线段树单点更新求最大值

题目链接 线段树入门题,线段树单点更新求最大值问题. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define N 200005 using namespace std; int data[N]; struct Tree { int l,r,ans; }tree[N*4]; void build(in

HDU - 3074 - Multiply game (线段树-单点更新,区间求积)

题目传送:Multiply game 思路:简单线段树,单点更新,区间求积,这是上次选拔赛选的题,一看题就是线段树,不过当时线段树不太熟,没敢敲,现在看来居然如此轻松,不过注意这里有大量输出,用printf,居然在这里TLE了一次... AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #incl

HDU 1166 敌兵布阵 线段树单点更新求和

题目链接 中文题,线段树入门题,单点更新求和,建一棵树就可以了. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define N 50005 using namespace std; int data[N]; struct Tree { int l,r,sum; }tree[N*4]; void bui

【原创】hdu 1166 敌兵布阵(线段树→单点更新,区间查询)

学习线段树的第三天...真的是没学点啥好的,又是一道水题,纯模板,我个人觉得我的线段树模板还是不错的(毕竟我第一天相当于啥都没学...找了一整天模板,对比了好几个,终于找到了自己喜欢的类型),中文题目嘛,直接上代码 我感觉我的代码有一个特点吧...有点啰嗦,但是每一行的思维和上一行紧密相连,新手看的话不会感到思维的跃迁,比较容易看懂,因为我之前看一些大神的代码,确实看到一半就不知道他下面啥意思了...所以希望我的代码能够造福新手吧=.= 1 #include<cstdio> 2 #includ

HDU 1754 I Hate It 线段树(单点更新,成段查询)

题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=1754 题解: 单点更新,成段查询. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lson o<<1 6 #define rson (o<<1)|1 7 #define M l+(r

hdu 6406 Taotao Picks Apples (2018 Multi-University Training Contest 8 1010)(二分,前缀和)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6406 思路: 暴力,预处理三个前缀和:[1,n]桃子会被摘掉,1到当前点的最大值,1到当前点被摘掉的桃子的数量,然后我们枚举修改p点造成的所有影响,: 1,假如新输入的点比原先的点的值更大,那么我们对修改后p这个点的值和[1,p-1]的最大值关系进行分析,也就是分析前半段的影响:(1)如果p点大于1-p-1的最大值的时候我们直接利用前缀和O(1)得到[1,p-1]有多少个桃子被摘掉,然后加上当前这个.(

HDU 1166 敌兵布阵 //线段树单点更新

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 41385    Accepted Submission(s): 17489 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务