zoukankan      html  css  js  c++  java
  • BZOJ1568:[JSOI2008]Blue Mary开公司

    浅谈标记永久化:https://www.cnblogs.com/AKMer/p/10137227.html

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1568

    什么是李超线段树?李超线段树就是用标记永久化维护平面内线段覆盖的线段树。

    对于这个题,对于每个区间,我们可以存下来在这个区间的中点(y)值最大的直线。

    对于添加一条线段,我们在线段树上对其进行递归替换原有标记:

    如果当前线段的斜率大于当前区间标记线段的斜率:

    如果在中点当前线段更大,由于斜率更大,说明在中点及中点以后的部分中,当前线段会比标记线段更优,我们先用标记线段去替换更新中点以前的部分,再把当前线段变成当前区间的标记线段。

    否则,递归用当前线段去替换更新中点以后的区间。

    如果当前线段的斜率小于当前区间标记线段的斜率:

    如果在中点当前线段更大,由于斜率更小,说明在中点及中点以前的部分中,当前线段会比标记线段更优,我们先用标记线段去替换更新中点以后的部分,再把当前线段变成当前区间的标记线段。
    否则,递归用当前线段去替换更新中点以前的区间。

    对于询问,就拿一个一个区间标记的直线算算取最大值就行了。

    时间复杂度:(O(NlogT))

    空间复杂度:(O(T))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
     
    const int maxn=5e4+5;
     
    int n,tot;
    char s[10];
    double b[maxn<<1],k[maxn<<1];
     
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
     
    inline double calc(int id,int x) {
        return b[id]+k[id]*(x-1);
    }
     
    struct segment_tree {
        int tag[maxn<<2];
     
        void change(int p,int l,int r,int id) {
            if(l==r) {
                if(calc(id,l)>calc(tag[p],l))tag[p]=id;
                return;
            }
            int mid=(l+r)>>1;
            if(k[id]>k[tag[p]]) {
                if(calc(id,mid)>calc(tag[p],mid))change(p<<1,l,mid,tag[p]),tag[p]=id;
                else change(p<<1|1,mid+1,r,id);
            }
            else {
                if(calc(id,mid)>calc(tag[p],mid))change(p<<1|1,mid+1,r,tag[p]),tag[p]=id;
                else change(p<<1,l,mid,id);
            }
        }
     
        double query(int p,int l,int r,int pos) {
            if(l==r)return calc(tag[p],l);
            int mid=(l+r)>>1;double ans=calc(tag[p],pos);
            if(pos<=mid)ans=max(ans,query(p<<1,l,mid,pos));
            else ans=max(ans,query(p<<1|1,mid+1,r,pos));
            return ans;
        }
    }T;
     
    int main() {
        n=read();
        for(int i=1;i<=n;i++) {
            scanf("%s",s+1);
            if(s[1]=='Q') {
                int pos=read();
                double ans=T.query(1,1,5e4,pos);
                printf("%d
    ",(int)(ans/100));
            }
            else {
                tot++;
                scanf("%lf%lf",b+tot,k+tot);
                T.change(1,1,5e4,tot);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    angularJs项目实战!02:前端的页面分解与组装
    angularJs项目实战!01:模块划分和目录组织
    django admin 导出数据简单示例
    django 学习之model操作(想细化)
    6.11大杂烩。。
    InlineModelAdmin对象的学习
    django-salmonella的使用
    python 保留两位小数
    Django 时间与时区设置问题
    Django学习
  • 原文地址:https://www.cnblogs.com/AKMer/p/10138264.html
Copyright © 2011-2022 走看看