zoukankan      html  css  js  c++  java
  • 陶陶摘苹果「线段树维护单调栈」

    题目描述

    题库后缀为contest/132/problem/2

    思路分析

    • 线段树维护单调栈板子题
    • 然而学长说会做楼房重建,就会做这道题,更巧的是我在十几天前刚做了这道题,当时过了也不知道还有线段树维护单调栈这种东西……,不过思路确实和线段树维护单调栈是一致的。

    关于线段树维护单调栈

    • 核心在于,在线段树中,其左儿子和右儿子会互相影响,这道题中显然就是右儿子会受到左儿子的影响
    • 目前本人比较偏向的板子中,核心是一个 calc 函数,传入两个参数——(rt)(w) ,(w) 代表 (rt) 节点所统领的区间所受到的限制的值。
    • 如果左儿子的最大值比 (w) 大,那么就递归左儿子,右儿子不必再递归,因为单调递增,右儿子的最小值一定大于等于左儿子的最大值。①
      否则递归右儿子,这时候左儿子一定不满足,而右儿子有可能满足。②
      还有就是到叶子节点的时候,直接和 (w) 比较一下就好了。③
    • 然后 pushup 的时候记得对右儿子调用 calc 函数(上面说的右儿子会受左儿子限制),以保证单调性

    (Code)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define R register
    #define N 100010
    using namespace std;
    inline int read(){
    	int x = 0,f = 1;
    	char ch = getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x*f;
    }
    int n,m,h[N];
    struct node{
    	int mx,len,l,r;//mx为区间最大值,len满足单调性的长度。
    }tr[N<<2];
    #define ls rt<<1
    #define rs rt<<1|1
    int calc(int rt,int w){
    	if(tr[rt].l==tr[rt].r)return tr[rt].mx > w;//③
    	if(tr[ls].mx>w)return calc(ls,w)+tr[rs].len;//①
    	else return calc(rs,w);//②
    }
    void pushup(int rt){
    	tr[rt].mx = max(tr[ls].mx,tr[rs].mx);
    	tr[rs].len = calc(rs,tr[ls].mx);//左儿子和谐右儿子
    }
    void build(int rt,int l,int r){
    	tr[rt].l = l,tr[rt].r = r;
    	if(l==r)return tr[rt].mx = h[l],void();
    	int mid = (l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    	pushup(rt);
    }
    void modify(int rt,int x){
    	if(tr[rt].l==tr[rt].r)return tr[rt].mx = h[tr[rt].l],void();
    	int mid = (tr[rt].l+tr[rt].r)>>1;
    	if(x<=mid)modify(ls,x);
    	else modify(rs,x);
    	pushup(rt);
    }
    int main(){
    #if 1
    	freopen("taopapp.in","r",stdin);
    	freopen("taopapp.out","w",stdout);
    #endif
    	n = read(),m = read();
    	for(R int i = 1;i <= n;i++)h[i] = read();
    	build(1,1,n);
    	for(R int i = 1;i <= m;i++){
    		int pos = read(),height = read();
    		int pre = h[pos];
    		h[pos] = height;
    		modify(1,pos);
    		printf("%d
    ",calc(1,-1));
    		h[pos] = pre;
    		modify(1,pos);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    python之shutil模块
    python的os模块
    python的map函数
    Web基础知识
    Web基础知识 --- html中的meta元素有什么用?
    使用技巧 --- 与 FireFox 相关
    基础知识之WIN32 API
    资料索引
    基础知识之C++篇
    使用技巧 --- 与 Visual Studio 有关
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/13800824.html
Copyright © 2011-2022 走看看