zoukankan      html  css  js  c++  java
  • UOJ #88. 【集训队互测2015】Robot 李超线段树

    李超线段树模板题,要同时维护最大值和最小值,然后求交点的时候注意 double 的转换

    code:

    #include <cstdio> 
    #include <cstring> 
    #include <cmath> 
    #include <cstdlib>    
    #include <vector>   
    #include <algorithm>
    #include <string>
    
    #define N 600007 
    #define eps 1e-14         
    #define ll long long  
    #define lson now<<1  
    #define rson now<<1|1  
    
    using namespace std; 
       
    void setIO(string s) 
    {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        // freopen(out.c_str(),"w",stdout); 
    }
    
    int cor[N],n,Q;    
    // y=kx+b    
    struct Line 
    {   
        int l,r;   
        ll k,b;   
        Line(int l=0,int r=0,ll k=0,ll b=0):l(l),r(r),k(k),b(b){}    
        ll calc(ll pos) { return pos*k+b; }    
        double cross(Line t) { return (double)(b-t.b)/(t.k-k); }        
    }smax[N<<2],smin[N<<2];  
       
    void build(int l,int r,int now) 
    {
        smax[now]=Line(l,r,0,0);   
        smin[now]=Line(l,r,0,0);   
        if(l==r) return;   
        int mid=(l+r)>>1;  
        build(l,mid,lson),build(mid+1,r,rson);  
    }
    
    void upmax(int l,int r,int now,Line k) 
    {         
        if(l>=k.l&&r<=k.r) 
        {
            if(k.calc(cor[l])>smax[now].calc(cor[l])&&k.calc(cor[r])>smax[now].calc(cor[r])) 
                smax[now]=k;   
            else if(k.calc(cor[l])>smax[now].calc(cor[l])||k.calc(cor[r])>smax[now].calc(cor[r]))   
            {               
                int mid=(l+r)>>1;   
                if(k.calc(cor[mid])>smax[now].calc(cor[mid])) 
                {   
                    Line tmp=smax[now];     
                    smax[now]=k,k=tmp;                   
                }    
                // 交点在中点右面        
                if(smax[now].cross(k)-(double)cor[mid]>eps) 
                    upmax(mid+1,r,rson,k);  
                else upmax(l,mid,lson,k);  
            }
            return; 
        }
        int mid=(l+r)>>1;               
        if(k.l<=mid)  upmax(l,mid,lson,k);  
        if(k.r>mid)   upmax(mid+1,r,rson,k);   
    }
         
    void upmin(int l,int r,int now,Line k) 
    {
        if(l>=k.l&&r<=k.r) 
        {
            if(k.calc(cor[l])<smin[now].calc(cor[l])&&k.calc(cor[r])<smin[now].calc(cor[r])) 
                smin[now]=k;    
            else if(k.calc(cor[l])<smin[now].calc(cor[l])||k.calc(cor[r])<smin[now].calc(cor[r]))   
            {
                int mid=(l+r)>>1;    
                if(k.calc(cor[mid])<smin[now].calc(cor[mid])) 
                {
                    Line tmp=smin[now];    
                    smin[now]=k,k=tmp;   
                }
                if(smin[now].cross(k)-(double)cor[mid]>eps)   
                    upmin(mid+1,r,rson,k);  
                else upmin(l,mid,lson,k);   
            }
            return; 
        }
        int mid=(l+r)>>1;   
        if(k.l<=mid)  upmin(l,mid,lson,k);  
        if(k.r>mid)   upmin(mid+1,r,rson,k);    
    }
    
    ll qmax(int l,int r,int now,int p) 
    {   
        if(l==r) return smax[now].calc(cor[l]);  
        int mid=(l+r)>>1;  
        ll re=smax[now].calc(cor[p]);      
        if(p<=mid) return max(re,qmax(l,mid,lson,p));  
        else return max(re,qmax(mid+1,r,rson,p));   
    }     
    
    ll qmin(int l,int r,int now,int p) 
    {
        if(l==r) return smin[now].calc(cor[p]);   
        int mid=(l+r)>>1;   
        ll re=smin[now].calc(cor[p]);    
        if(p<=mid) return min(re,qmin(l,mid,lson,p));   
        else return min(re,qmin(mid+1,r,rson,p));    
    }
    
    struct li  
    {
        int s,t; 
        ll k,b;   
        li(int s=0,int t=0,ll k=0,ll b=0):s(s),t(t),k(k),b(b){}   
    };  
    vector<li>G[N];    
    int a[N],A[N],ask[N];      
    
    int main() 
    { 
        // setIO("input");                
        scanf("%d%d",&n,&Q);    
        for(int i=1;i<=n;++i)   
        { 
            scanf("%d",&a[i]); 
            G[i].push_back(li(0,1e9,0,a[i]));   
        }
        char op[10];
        int q=0,tot=0;           
        A[++tot]=0,A[++tot]=1e9;     
        for(int i=1;i<=Q;++i) 
        {
            int t;     
            scanf("%d%s",&t,op),A[++tot]=t;          
            if(op[0]=='c') 
            {
                int x,k;   
                scanf("%d%d",&x,&k);                   
                G[x][G[x].size()-1].t=t;    
                li pr=G[x][G[x].size()-1];           
                G[x].push_back(li(t,1e9,k,pr.k*t+pr.b-(ll)k*t));         
            }
            else ask[++q]=t;    
        }
        sort(A+1,A+1+tot);    
        int T=unique(A+1,A+1+tot)-A-1;         
        for(int i=1;i<=T;++i) cor[i]=A[i];
        for(int i=1;i<=q;++i) ask[i]=lower_bound(A+1,A+1+T,ask[i])-A;               
        for(int i=1;i<=n;++i) 
        {
            for(int j=0;j<G[i].size();++j) 
            {
                G[i][j].s=lower_bound(A+1,A+1+T,G[i][j].s)-A;   
                G[i][j].t=lower_bound(A+1,A+1+T,G[i][j].t)-A;     
            }
        }            
        build(1,T,1);              
        for(int i=1;i<=n;++i) 
        {
            for(int j=0;j<G[i].size();++j)  
            {
                Line k=Line(G[i][j].s,G[i][j].t,G[i][j].k,G[i][j].b);    
                upmax(1,T,1,k);    
                upmin(1,T,1,k);    
            }
        }      
        for(int i=1;i<=q;++i)    
            printf("%lld
    ",max(qmax(1,T,1,ask[i]),-qmin(1,T,1,ask[i])));       
        return 0;       
    }
    

      

  • 相关阅读:
    去除 .sh 文件的
    Shell Notepad++导致报错:#!/bin/bash: 坏的解释器: 没有那个文件或目录
    linux 不同格式的软件包的安装
    linux:jenkins 默认安装目录
    使用nsis制作的安装包安装后,无法卸载干净的问题
    bash: ./t.sh:/bin/bash^M:损坏的解释器: 没有那个文件或目录
    jenkins启动/重启/停止命令 改端口
    解决windows系统80端口被占用问题
    find ./ -name *.bak | xargs rm -rf
    Linux查看端口占用情况,释放占用的端口
  • 原文地址:https://www.cnblogs.com/guangheli/p/12868368.html
Copyright © 2011-2022 走看看