zoukankan      html  css  js  c++  java
  • bzoj2957楼房重建

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2957

    线段树。每个点记录斜率,要一个单增的序列长度(从1开始)。

    线段树每个点记录自己区间的max和单增长度,pushup的时候通过mx [ ls ]判断往哪个儿子递归。

    需要注意的是当右儿子的长度全部可以加上是,不能加s [ rs ],因为不一定全在总的单增序列上(只有rs中大于mx[ls]的那一部分);

      所以右儿子的贡献应该是原先总区间的s减去左儿子的s,因为单增序列从最左端开始,总序列中左儿子肯定全在。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    int n,m,x,s[N<<2];
    double z,mx[N<<2];
    int dg(int cur,double lm,int l,int r)
    {
        if(l==r)return mx[cur]>lm;
        int ls=(cur<<1),rs=(cur<<1|1);
        if(mx[ls]<=lm)return dg(rs,lm,((l+r)>>1)+1,r);
        return dg(ls,lm,l,((l+r)>>1))+s[cur]-s[ls];
    }
    void pushup(int bh,int l,int r)
    {
        int ls=(bh<<1),rs=(bh<<1|1);
        mx[bh]=mx[ls];s[bh]=s[ls];
        if(mx[rs]<=mx[ls])return;
        mx[bh]=mx[rs];
    //    printf(" ()l=%d r=%d mx=%lf
    ",l,r,mx[bh]);
        s[bh]+=dg(rs,mx[ls],((l+r)>>1)+1,r);
    }
    void add(int bh,int l,int r)
    {
        int mid=((l+r)>>1);
        if(l==r){
            mx[bh]=z;s[bh]=1;//bh,不是l 
    //        printf("l=%d r=%d mx=%lf s=%d
    ",l,r,mx[bh],s[bh]);
            return;
        }
        if(x<=mid)add(bh<<1,l,mid);
        else add(bh<<1|1,mid+1,r);
        pushup(bh,l,r);
    //    printf("l=%d r=%d mx=%lf s=%d
    ",l,r,mx[bh],s[bh]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%lf",&x,&z);z/=x;
            add(1,1,n);
            printf("%d
    ",s[1]);
        }
        return 0;
    }
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/Narh/p/8969298.html
Copyright © 2011-2022 走看看