李超线段树

宏定义

  • #define pl p<<1\texttt{\#define pl p<<1}:节点 pp 的左儿子。
  • #define pr p<<1|1\texttt{\#define pr p<<1|1}:节点 pp 的右儿子。

常量与变量

  • Tree a[i]\texttt{Tree a[i]}:节点 ii 的信息。
  • int a[i].l\texttt{int a[i].l}:节点 ii 维护的区间的左端点。
  • int a[i].r\texttt{int a[i].r}:节点 ii 维护的区间的右端点。
  • long long a[i].k\texttt{long long a[i].k}:节点 ii 所管理的区间的最优线段的斜率。
  • long long a[i].b\texttt{long long a[i].b}:节点 ii 所管理的区间的最优线段的截距。

函数

  • void build(int p,int l,int r)\texttt{void build(int p,int l,int r)}:在外调用时,表示以节点 pp 为根,建议一颗区间范围为 lrl\sim r 的线段树。
  • void change(int p,int l,int r,long long k,long long b)\texttt{void change(int p,int l,int r,long long k,long long b)}:在节点 pp 管理的区间中插入一条横坐标区间为 [l,r][l,r],斜率为 kk,截距为 bb 的线段。
  • long long ask(int p,int x)\texttt{long long ask(int p,int x)}:求出节点 pp 掌管的区间内所有线段的横坐标取 xx 时得到的最大的 yy 值。

代码

#define pl p<<1
#define pr p<<1|1
struct Segment_Tree{
    struct Tree{
        int l,r;
        long long k,b;
    }a[N<<2];
    void build(int p,int l,int r){
        a[p].l=l;a[p].r=r;
        a[p].k=0;a[p].b=0;
        if(l==r)
            return;
        int mid=(l+r)>>1;
        build(pl,l,mid);
        build(pr,mid+1,r);
    }
    void change(int p,int l,int r,long long k,long long b){
        int mid=(a[p].l+a[p].r)>>1;
        if(l<=a[p].l&&a[p].r<=r){
            ll x0=a[p].l,x1=a[p].r;
            ll py0=a[p].k*x0+a[p].b,py1=a[p].k*x1+a[p].b,py2=a[p].k*mid+a[p].b;
            ll ny0=k*x0+b,ny1=k*x1+b,ny2=k*mid+b;
            if(ny0>=py0&&ny1>=py1)
            	a[p].k=k,a[p].b=b;
            else if(ny0<=py0&&ny1<=py1)
            	return;
            else{
            	if(ny0>py0){
            		if(ny2<py2)
            			change(pl,l,r,k,b);
            		else{
            			change(pr,l,r,a[p].k,a[p].b);
            			a[p].k=k,a[p].b=b;
					}
				}
				else{
            		if(ny2>py2){
            			change(pl,l,r,a[p].k,a[p].b);
            			a[p].k=k,a[p].b=b;
					}
            		else
            			change(pr,l,r,k,b);
				}
			}
			return;
        }
        if(l<=mid)
            change(pl,l,r,k,b);
        if(r>mid)
            change(pr,l,r,k,b);
    }
    long long ask(int p,int x){
		ll ans=x*a[p].k+a[p].b;
		if(a[p].l==a[p].r)
			return ans;
        int mid=(a[p].l+a[p].r)>>1;
        if(x<=mid)
        	ans=max(ans,ask(pl,x));
        else
        	ans=max(ans,ask(pr,x));
		return ans;
    }
}tree;
posted @ 2022-06-05 00:24  luckydrawbox  阅读(9)  评论(0)    收藏  举报  来源