• bzoj 2957: 楼房重建


    题目

    这道题真是非常巧妙了

    首先分析一下对于一个楼房(i)它要是想能被看见需要满足什么条件

    显然对于任意的(j<i)需要满足

    [frac{h_i}{i} imes j>h_j ]

    也就是

    [frac{h_i}{i}>frac{h_j}{j} ]

    也就是一个从(1)开始的最长上升子序列

    那么还有单点修改,这是一个动态(dp)?

    当然不是了,这里需要一个非常巧妙的(pushup)

    我们设线段树上区间(i)里的最大斜率是(mx_i),答案是(len_i)

    这个时候我们需要将(ls)(rs)合并起来,非常显然(len_{ls})直接会被计入答案,而我们要考虑左区间的最大斜率对右区间的影响

    那么我们就去右区间里找到第一个比(mx_{ls})大的斜率,统计出从这个点开始的最长上升子序列

    那么我们就去右区间里找,这个相当于做一次查询,于是整体复杂度是(O(mlog^2n))

    至于如何在右区间里找,就在代码里说了,总之神仙的一批

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 100005
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int n,m;
    int a[maxn];
    int l[maxn<<2],r[maxn<<2],len[maxn<<2];
    double mx[maxn<<2];
    int query(int i,double t)
    {
    	if(mx[i]<t) return 0;
    	if(l[i]==r[i]) return mx[i]>t;
    	if(mx[i<<1]>t) return len[i]-len[i<<1]+query(i<<1,t);
    	//如果左区间的最大值就已经比t大了,那么说明右区间的相对于左区间最大值开始LIS长度可以被计入答案了
    	//怎么快速算这个LIS长度,显然再去右区间里找并不能保证复杂度
    	//但是看看下面的pushup, len[i]=len[i<<1]+query(i<<1|1,mx[i<<1]);
    	//那么整个区间的答案减掉左区间的答案不就是区间的相对于左区间最大值开始LIS长度吗 
    	return query(i<<1|1,t);
    }
    void build(int x,int y,int i)
    {
    	l[i]=x,r[i]=y;
    	if(x==y) return;
    	int mid=x+y>>1;
    	build(x,mid,i<<1),build(mid+1,y,i<<1|1);
    }
    void change(int pos,double val,int i)
    {
    	if(l[i]==r[i])
    	{
    		mx[i]=val;
    		len[i]=1;
    		return;
    	} 
    	int mid=l[i]+r[i]>>1;
    	if(pos<=mid) change(pos,val,i<<1);
    	else change(pos,val,i<<1|1);
    	mx[i]=max(mx[i<<1],mx[i<<1|1]);
    	len[i]=len[i<<1]+query(i<<1|1,mx[i<<1]);
    	//左区间直接计入答案,递归去右区间里找 
    }
    int main()
    {
    	n=read(),m=read();
    	build(1,n,1);
    	int pos,val;
    	while(m--)
    	{
    		pos=read(),val=read();
    		change(pos,double(val)/double(pos),1);
    		printf("%d
    ",len[1]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    json dump dumps load loads
    python tip: 格式化 深浅copy sorted
    转载整理
    python 计算器练习
    实验5 OSPF虚连接和验证配置
    实验4 OSPF的特殊区域STUB和NSSA
    实验3ospf路由聚合
    实验2 OSPF基本配置
    实验1静态ECMP的浮动静态路由配置
    补充实验6:tftp
  • 原文地址:https://www.cnblogs.com/asuldb/p/10324916.html
Copyright © 2020-2023  润新知