zoukankan      html  css  js  c++  java
  • 线段树维护一次函数

    评测地址:https://www.codechef.com/problems/STREETTA

    操作1:[l,r] 函数A对ax+b取大

    操作2:[l,r] 函数B增加一次函数ax+b

    操作3:询问 函数A在x位置的最大值+函数B在x位置的值,没有输出NA

    r<=1e9

    |a|,|b|<=1e9

    操作数<=3e5

    每次操作大约用log个节点,标记下传还要带log,所以线段树动态开节点

    线段树标记永久化,询问从根一直走到它

    函数增加直接加

    函数取大:

    1、原区间无函数,直接覆盖

    2、无交点,用截距大的覆盖

    3、交点在区间左端点,用斜率大的覆盖

    4、交点在区间右端点,用斜率小的覆盖

    5、交点在左子区间,下传截距大的,留下截距小的

    6、交点在右子区间,下传截距小的,留下截距大的

    (5、6 是在区间内部有交点,一定有一个函数只会影响一个子区间,下传这个函数)

    下传函数时,

    往左子区间传,斜率、截距都不改变

    往右子区间传,斜率不变,截距改变

    注意:代码中求函数交点,得到的是交点位置是将区间左端点看做0

    #include<cmath>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    #define N 300001
    
    const double eps=1e-7;
    
    struct node
    {
        LL mxa,mxb;
        LL sma,smb;
        int lc,rc;
        bool HaveMx;
    }tr[N*70];
    
    int tot;
    
    bool ok;
    
    LL AnsMx,AnsSm;
    
    void read(int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
    
    void query(int k,int l,int r,int pos)
    {
        if(tr[k].HaveMx)
        {
            ok=true;
            AnsMx=max(AnsMx,(pos-l)*tr[k].mxa+tr[k].mxb);
        }
        AnsSm+=(pos-l)*tr[k].sma+tr[k].smb;
        if(l==r) return;
        int mid=l+r>>1;
        if(pos<=mid)
        {
            if(tr[k].lc) query(tr[k].lc,l,mid,pos);
        }
        else
        {
            if(tr[k].rc) query(tr[k].rc,mid+1,r,pos);
        }
    }
    
    void add(int &k,int l,int r,int opl,int opr,LL a,LL b)
    {
        if(!k) k=++tot;
        if(l==opl && r==opr)
        {
            tr[k].sma+=a;
            tr[k].smb+=b;
            return;
        }
        int mid=l+r>>1;
        if(opr<=mid) add(tr[k].lc,l,mid,opl,opr,a,b);
        else if(opl>mid) add(tr[k].rc,mid+1,r,opl,opr,a,b);
        else
        {
            add(tr[k].lc,l,mid,opl,mid,a,b);
            add(tr[k].rc,mid+1,r,mid+1,opr,a,a*(mid+1-opl)+b);
        }
    }
    
    double getpoint(LL a1,LL b1,LL a2,LL b2)
    {
        return 1.0*(b2-b1)/(a1-a2);
    }
    
    bool dcmp(double x,double y)
    {
        return fabs(x-y)<eps;
    }
    
    void down(int &k,int l,int r,LL a,LL b)
    {
        if(!k) k=++tot;
        if(l==r)
        {
            if(!tr[k].HaveMx)
            {
                tr[k].HaveMx=true;
                tr[k].mxa=a;
                tr[k].mxb=b;
            }
            else
            {
                if(b>tr[k].mxb)
                {
                    tr[k].mxa=a;
                    tr[k].mxb=b;
                }
            }
            return;
        }
        if(!tr[k].HaveMx)
        {
            tr[k].HaveMx=true;
            tr[k].mxa=a;
            tr[k].mxb=b;
        }
        else
        {
            if(a==tr[k].mxa)
            {
                if(b>tr[k].mxb) tr[k].mxb=b;
                return;
            }
            double foot=getpoint(a,b,tr[k].mxa,tr[k].mxb);
            if(foot<0 || foot>r-l+1)
            {
                if(b>tr[k].mxb)
                {
                    tr[k].mxa=a;
                    tr[k].mxb=b;
                }
            }
            else if(dcmp(foot,0))
            {
                if(a>tr[k].mxa)
                {
                    tr[k].mxa=a;
                    tr[k].mxb=b;
                }
            }
            else if(dcmp(foot,r-l+1))
            {
                if(a<tr[k].mxa)
                {
                    tr[k].mxa=a;
                    tr[k].mxb=b;
                }
            }
            else 
            {
                int mid=l+r>>1;
                if(l+foot<=mid)
                {
                    if(b>tr[k].mxb) down(tr[k].lc,l,mid,a,b);
                    else
                    {
                        down(tr[k].lc,l,mid,tr[k].mxa,tr[k].mxb);
                        tr[k].mxa=a;
                        tr[k].mxb=b;
                    }
                }
                else
                {
                    if(b<tr[k].mxb) down(tr[k].rc,mid+1,r,a,a*(mid+1-l)+b);    
                    else
                    {
                        down(tr[k].rc,mid+1,r,tr[k].mxa,tr[k].mxa*(mid+1-l)+tr[k].mxb);
                        tr[k].mxa=a;
                        tr[k].mxb=b;
                    }
                }
            }
        }
    }
    
    void getmax(int &k,int l,int r,int opl,int opr,LL a,LL b)
    {
        if(!k) k=++tot;
        if(l==opl && r==opr)
        {
            down(k,l,r,a,b);
            return;
        }
        int mid=l+r>>1;
        if(opr<=mid) getmax(tr[k].lc,l,mid,opl,opr,a,b);
        else if(opl>mid) getmax(tr[k].rc,mid+1,r,opl,opr,a,b);
        else
        {
            getmax(tr[k].lc,l,mid,opl,mid,a,b);
            getmax(tr[k].rc,mid+1,r,mid+1,opr,a,a*(mid+1-opl)+b);
        }
    }
    
    int main()
    {
        freopen("data.in","r",stdin);
        freopen("my.out","w",stdout);
        int n,m;
        read(n);
        read(m);
        int ty,l,r,a,b;
        int root=0;
        while(m--)
        {
            read(ty);
            if(ty==1)
            {
                read(l); read(r); read(a); read(b);
                getmax(root,1,n,l,r,a,b);
            }
            else if(ty==2)
            {
                read(l); read(r); read(a); read(b);
                add(root,1,n,l,r,a,b);
            }
            else
            {
                read(l);
                ok=false;
                AnsMx=-1LL<<62;
                AnsSm=0;
                query(root,1,n,l);
                if(!ok) puts("NA");
                else cout<<AnsMx+AnsSm<<'
    ';
            }
        }
    }
  • 相关阅读:
    win7_64 下redis安装并进行php-redis扩展
    redis 与 memcache 性能测试比较
    前端一班:HTML5当天学习总结-摘抄张果博客园
    Hibernate ORM框架——项目一:Hibernate事务的生命周期,不建议使用openSession而改造
    Hibernate ORM框架——Hibernate查询之Criteria接口、Native SQL 查询、Query接口(批量操作)
    Hibernate ORM框架——Hibernate分页查询and多表查询
    Hibernate ORM框架——项目一:Hibernate查询;项目二:集合相关查询
    Hibernate ORM框架——连接池相关
    Hibernate ORM框架——综合
    Hibernate ORM框架——续第二章:Hibernate映射关系:双向关联
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8150957.html
Copyright © 2011-2022 走看看