zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    XAF 有条件的对象访问权限
    XAF 顯示 UnInplace Report(設置自定義條件顯示報表,不是根據選擇ListView記錄條件顯示報表)
    XAF 如何自定义PivotGrid单元格显示文本?
    XAF 如何布局详细视图上的按钮
    XAF How to set size of a popup detail view
    XAF Delta Replication Module for Devexpress eXpressApp Framework
    XAF 帮助文档翻译 EasyTest Basics(基础)
    XAF 用户双击ListView记录时禁止显示DetailView
    XAF How to enable LayoutView mode in the GridControl in List Views
    XAF 如何实现ListView单元格批量更改?
  • 原文地址:https://www.cnblogs.com/asuldb/p/10324916.html
Copyright © 2011-2022 走看看