zoukankan      html  css  js  c++  java
  • 洛谷4198 楼房重建(线段树)

    神仙题。pb 说是套路题???

    首先只有楼房顶有用,然后要斜率递增。

    没事干了,上线段树。

    肯定要记录区间单调队列的长度 (len)。当然把整个能看到的位置都记下来会更方便,然而复杂度就爆了。

    顺便再来个区间最大值 (mx)

    修改是单点,叶子很好搞。询问就是根节点的 (len)

    难点就在 pushup。

    (mx) 不管,只看 (len)

    首先发现,最左边的和最大值都能看到。

    pushup 时,首先左边的所有数都仍然能被看到,右边能看到的数的个数和左边的最大值有关,右边留下的只有大于左边最大值的数。

    所以我们递归 pushup:

    参数有:线段树节点编号 (o) 和能看到的数的下界 (lwr)(也就是只保留 (>lwr) 的数,然后再求看不看得到)

    如果 (mx_ole lwr),整个区间都不能看到。

    如果 (a_l>lwr),那么答案就是 (len_o)(能看到的数和没有这个下界没区别)。

    如果 (mx_{lson}le lwr),那么左儿子全都没有,递归到右儿子 (pushup(rson,lwr))

    否则左儿子的最大值肯定保留了下来,那么右儿子能看到的数与没有下界没有区别,个数是 (len_o-len_{lson})。递归到左儿子 (pushup(lson,lwr)+len_o-len_{lson})

    这样 pushup 一次是 (O(log n))

    时间复杂度 (O(mlog^2n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN=400040;
    #define ls o<<1
    #define rs o<<1|1
    #define lson ls,l,mid
    #define rson rs,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    template<typename T>
    inline void read(T &x){
    	x=0;
    	char ch=getchar();bool f=false;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	if(f) x=-x;
    }
    int n,m,len[MAXN];
    double a[MAXN],mx[MAXN];
    inline void pushup1(int o){
    	mx[o]=max(mx[ls],mx[rs]);
    }
    int pushup2(int o,int l,int r,double lwr){
    	if(a[l]>lwr) return len[o];
    	if(mx[o]<=lwr) return 0;
    	int mid=(l+r)>>1;
    	if(mx[ls]<=lwr) return pushup2(rson,lwr);
    	else return pushup2(lson,lwr)+len[o]-len[ls];
    }
    inline void pushup(int o,int l,int r){
    	pushup1(o);
    	int mid=(l+r)>>1;
    	len[o]=len[ls]+pushup2(rson,mx[ls]);
    }
    void update(int o,int l,int r,int p,double v){
    	if(l==r) return void((mx[o]=v,len[o]=1));
    	int mid=(l+r)>>1;
    	if(mid>=p) update(lson,p,v);
    	if(mid<p) update(rson,p,v);
    	pushup(o,l,r);
    }
    int main(){
    	read(n);read(m);
    	while(m--){
    		int x,y;
    		read(x);read(y);
    		update(1,1,n,x,a[x]=1.0*y/x);
    		printf("%d
    ",len[1]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    ServletWebServerApplicationContext -带有*WebxxxApplication的容器
    SpringMvc-DispatchServlet初始化
    SimpleDateFormat和java8日期格式化
    01导入配置类和用户自定义添加db。ImportBeanDefinitionRegistrar和DeferredImportSelector
    @ConfigurationProperties和@PropertySource
    mybatis语句的存储
    leetCode3: 无重复字符的最长子串
    八锁问题
    数据库杂记
    背包问题
  • 原文地址:https://www.cnblogs.com/1000Suns/p/11976014.html
Copyright © 2011-2022 走看看