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;
    }
    
  • 相关阅读:
    UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
    UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
    【Same Tree】cpp
    【Recover Binary Search Tree】cpp
    【Binary Tree Zigzag Level Order Traversal】cpp
    【Binary Tree Level Order Traversal II 】cpp
    【Binary Tree Level Order Traversal】cpp
    【Binary Tree Post order Traversal】cpp
    【Binary Tree Inorder Traversal】cpp
    【Binary Tree Preorder Traversal】cpp
  • 原文地址:https://www.cnblogs.com/AKMer/p/10138264.html
Copyright © 2011-2022 走看看