• BZOJ 2957 楼房重建


    Description

    小A的楼房外有一大片施工工地,工地上有(N)栋待建的楼房。每天,这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆,数自己能够看到多少栋房子。
    为了简化问题,我们考虑这些事件发生在一个二维平面上。小A在平面上((0,0))点的位置,第i栋楼房可以用一条连接((i,0))((i,H_{i}))的线段表示,其中(H_{i})为第(i)栋楼房的高度。如果这栋楼房上任何一个高度大于(0)的点与((0,0))的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。
    施工队的建造总共进行了(M)天。初始时,所有楼房都还没有开始建造,它们的高度均为(0)。在第(i)天,建筑队将会将横坐标为(X_{i})的房屋的高度变为(Y_{i})(高度可以比原来大---修建,也可以比原来小---拆除,甚至可以保持不变---建筑队这天什么事也没做)。请你帮小A数数每天在建筑队完工之后,他能看到多少栋楼房?

    Input

    第一行两个正整数(N,M)
    接下来(M)行,每行两个正整数(X_{i},Y_{i})

    Output

    M行,第i行一个整数表示第(i)天过后小A能看到的楼房有多少栋。

    Sample Input

    3 4
    2 4
    3 6
    1 1000000000
    1 1

    Sample Output

    1
    1
    1
    2

    Hint

    数据约定

    对于所有的数据(1 le X_{i} le N)(1 le Y_{i} le 10^{9})
    (N,M le 100000)

    很早就听说过这一题的大名,却一直没有去写,今天来写一下。
    我们用线段树来维护斜率的一条上升的链,(L_{i})表示链左端的斜率,(R_{i})表示链右端的斜率。
    考虑如何维护,对于区间(l sim r)一段区间,我们用(l sim mid)这段的右端点,放到(mid+1 sim r)中询问,复杂度(O(nlog^{2}n))

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    #define eps (1e-12)
    #define maxn 400010
    int n,m,len[maxn]; double L[maxn],R[maxn];
    
    inline bool equal(double a,double b) { return fabs(a-b) < eps; }
    inline bool dy(double a,double b) { if (equal(a,b)) return false; return a > b; }
    inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; }
    
    inline void query(int l,int r,int now,int &k1,double &k2)
    {
    	if (dy(L[now],k2)) k1 += len[now],k2 = R[now];
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (xd(R[now<<1],k2)) query(mid+1,r,now<<1|1,k1,k2);
    	else
    	{
    		query(l,mid,now<<1,k1,k2);
    		k1 += len[now] - len[now<<1]; k2 = R[now];
    	}
    }
    inline void update(int l,int r,int now)
    {
    	len[now] = len[now<<1],L[now] = L[now<<1],R[now] = R[now<<1];
    	int mid = (l + r) >> 1;
    	query(mid+1,r,now<<1|1,len[now],R[now]);
    }
    inline void change(int l,int r,int x,int y,int now)
    {
    	if (l == r) { L[now] = R[now] = 1.0*y/x; len[now] = (y > 0); return; }
    	int mid = (l + r) >> 1;
    	if (x <= mid) change(l,mid,x,y,now<<1);
    	else change(mid+1,r,x,y,now<<1|1);
    	update(l,r,now);
    }
    
    int main()
    {
    	freopen("2957.in","r",stdin);
    	freopen("2957.out","w",stdout);
    	scanf("%d %d",&n,&m);
    	while (m--)
    	{
    		int x,y; scanf("%d %d",&x,&y);
    		change(1,n,x,y,1);
    		printf("%d
    ",len[1]);
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    hadoop中namenode发生故障的处理方法
    开启虚拟机所报的错误:VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program, access all directories the program uses, and access all directories for temporary fil
    Hbase的安装与部署(集群版)
    分别用反射、编程接口的方式创建DataFrame
    用Mapreduce求共同好友
    SparkSteaming中直连与receiver两种方式的区别
    privot函数使用
    Ajax无刷新显示
    使用ScriptManager服务器控件前后台数据交互
    数据库知识
  • 原文地址:https://www.cnblogs.com/mmlz/p/4424741.html
Copyright © 2020-2023  润新知