大约是一颗李超线段树

孤街醉人 提交于 2019-12-04 10:46:35

%%%

由于观看Joe大神颓废学习发现了这种高级数据结构

才引来了这场灾难(我先改完T2才改完T1

说明书:

用途:维护最优一次函数

复杂度:$\Theta (n log_{2}n^{2})$

使用指南:

我们先把线段树节点中存储的信息改为存储一条线

存储的线段不一定在区间的每个点上都最有,但是应该是在该区间最优的

有没有感觉很像二维MLE线段树

当然也可能有这么两条线分别在同一区间不同位置最优

此时维护优的区间更长的

(以下假设维护最大值

区间修改:

  我们考虑两根线段

  首先我们要将线段在线段树上定位,此时会有$ log_{2}n$个区间需要修改

  接下来我们只考虑一个区间了哈

  经对两根线段的相对位置大力分类讨论得:

  一共有四种情况

  1.

    

 

 

     线段$a$(蓝色)的斜率比当前最优线段$b$(或许是橙色)小

  且两线段交点在中点右侧

  那么显然对于当前区间以及左侧区间线段$a$更优,

  递归到这里就可以停了(当前区间已经被修改后再去修改左侧区间毫无意义

  但是对于右侧区间

  线段$b$仍可能更优

  此时应以线段$b$为参数递归修改右侧区间

  2.

   

 

     线段$a$(同上)的斜率比当前最优线段$b$(同上)小

  且两线段交点在中点左侧

  线段$a$仅在左侧区间可能更优

  此时应以线段$a$为参数递归修改左侧区间

  3.

  

 

       线段$a$(同上)的斜率比当前最优线段$b$(同上)大

  且两线段交点在中点右侧

  线段$a$仅在右侧区间可能更优

  此时应以线段$a$为参数递归修改右侧区间

  4.

  

 

   

       线段$a$(同上)的斜率比当前最优线段$b$(同上)大

  且两线段交点在中点左侧

  对于当前区间以及左侧区间线段$b$更优,

  此时应以线段$b$为参数递归修改左侧区间

单点查询:

  正常查询即可

  注意应在每个节点取一次最值

  因为最优解及可能来自叶节点

  也有可能来自祖先节点

另附本次考试T1代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define cin(k) scanf("%lld",&k)
#define l(k) ((k)<<1)
#define r(k) (l(k)|1)
const int maxn=64646,base=32323;
struct line{int k,b;};
struct Tree{
	struct tree{
		int bo;
		line li;
	}t[base<<3];
	bool cmp(int p,line x,line y)
	{
		p-=base;
		return x.k*p+x.b>=y.k*p+y.b;
	}
	void add(int k,int l,int r,line li)
	{
		if(l==r)
		{
			if(cmp(l,li,t[k].li))	t[k].li=li;
			return;
		}
		int mid=(l+r)>>1;
		if(t[k].li.k<=li.k)
		{
			if(cmp(mid,li,t[k].li))
			{
				add(l(k),l,mid,t[k].li);
				t[k].li=li;
			}
			else
				add(r(k),mid+1,r,li);
		}
		else
		{
			if(cmp(mid,li,t[k].li))
			{
				add(r(k),mid+1,r,t[k].li);
				t[k].li=li;
			}
			else
				add(l(k),l,mid,li);
		}
	}
	int query(int k,int l,int r,int p,int res)
	{
		int ans=t[k].li.k*(p-base)+t[k].li.b;
		if(l==r)	return ans;
		int mid=(l+r)>>1;
//		if(res)
		{
			if(p<=mid)	return max(ans,query(l(k),l,mid,p,res));
			else		return max(ans,query(r(k),mid+1,r,p,res));
		}
/*		else
		{
			if(p<=mid)	return min(ans,query(l(k),l,mid,p,res));
			else		return min(ans,query(r(k),mid+1,r,p,res));
		}
*/	}
}S,T;
int n,qu;
int ans[maxn+1];
signed main()
{
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
	cin(n);cin(qu);
	for(int q=1;q<=n;q++)
	{
		int a,b;cin(a),cin(b);
		S.add(1,base+1,maxn,(line){a,b});
		T.add(1,1,base-1,(line){-a,-b});
	}
	for(int q=-32322;q<=32322;q++)
	{
		if(q>0)			ans[q+base]=S.query(1,base+1,maxn,q+base,1)*q;
		else if(q<0)	ans[q+base]=-T.query(1,1,base-1,q+base,0)*q;
		else			ans[q+base]=0;
	}
	for(int q=1;q<=qu;q++)
	{
		int x;cin(x);
		printf("%lld\n",ans[x+base]);
	}
}

区间查询:

404

唔……未找到该页面……你是从哪里点进来的……>_<……

作者已死

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!