李超线段树模板入门

· · 个人记录

李超线段树模板入门

李超线段树用于解决如下问题:

线段树上的每一个节点维护该节点所代表区间的最优线段

称一个区间的最优线段为完整覆盖该区间的所有线段中在该区间中点y值最大的那一条

修改

注意

李超线段树并不严格 对于一个可能在较多区间最优的线段 存储时它有可能只在它最优的最高的那个区间最优 这要求我们在更新时应该递归进入一条线段可能为最优的那个区间

对于一条线段 我们递归的修改

首先 对于一条线段的修改 仿照线段树区间修改

考虑

查询

若查询一点 则找出包含该点的所有区间 比较这些区间中的最大值即可

代码

#include<bits/stdc++.h>
using namespace std;
#define mod1 39989
#define mod2 1000000000
#define N 500005
#define mid1 ((l+r)>>1)
#define mid ((tr[x].l+tr[x].r)>>1)
int n,xdcnt=0;
int tans[N];
struct XD
{
  int x_0,y_0,x_1,y_1;
  double k;
}xd[N];
struct nd
{
  int l,r,cxd=0;
}tr[N<<4];
double zdy(int x,int k)
{
  return xd[x].y_0+xd[x].k*(k-xd[x].x_0)*1.0;
}
void build(int x,int l,int r)
{
  tr[x].l=l;
  tr[x].r=r;
  if(l==r)
    return;
  build(x<<1,l,mid1);
  build(x<<1|1,mid1+1,r);
}
void insert(int x,int k)
{
  if(xd[k].x_0<=tr[x].l&&tr[x].r<=xd[k].x_1)
  {
    if(tr[x].cxd==0)
    {
      tr[x].cxd=k;
      return;
    }
    if(zdy(k,tr[x].l)<=zdy(tr[x].cxd,tr[x].l)&&zdy(k,tr[x].r)<=zdy(tr[x].cxd,tr[x].r))
      return;
    if(zdy(k,tr[x].l)>=zdy(tr[x].cxd,tr[x].l)&&zdy(k,tr[x].r)>=zdy(tr[x].cxd,tr[x].r))
    {
      tr[x].cxd=k;
      return;
    }
    if(zdy(k,mid)>=zdy(tr[x].cxd,mid))
    {
      if(xd[k].k>xd[tr[x].cxd].k)
        insert(x<<1,tr[x].cxd);
      else
        insert(x<<1|1,tr[x].cxd);
      tr[x].cxd=k;
    }
    else
      if(xd[k].k>xd[tr[x].cxd].k)
        insert(x<<1|1,k);
      else
        insert(x<<1,k);
  }
  else
  {
    if(xd[k].x_0<=mid)
      insert(x<<1,k);
    if(xd[k].x_1>mid)
      insert(x<<1|1,k);
  }
}
int ask(int x,int k)
{
  int lans;
  if(tr[x].l==tr[x].r)
    return tr[x].cxd;
  if(k<=mid)
    lans=ask(x<<1,k);
  else
    lans=ask(x<<1|1,k);
  if(zdy(lans,k)>zdy(tr[x].cxd,k))
    return lans;
  else if(zdy(lans,k)==zdy(tr[x].cxd,k))
    return max(tr[x].cxd,lans);
  else
    return tr[x].cxd;
}
int main()
{
  //freopen("in.my","r",stdin);
  //freopen("out.my","w",stdout);
  int lastans=0;
  scanf("%d",&n);
  build(1,1,100000);
  for(int i=1;i<=n;i++)
  {
    int op,x_0,x_1,y_0,y_1,x;
    scanf("%d",&op);
    if(op==0)
    {
      scanf("%d",&x);
      x=(x+lastans-1+mod1)%mod1+1;
      int ans;
      ans=ask(1,x);
      //if(zdy(ans,x)<max(xd[tans[x]].y_0,xd[tans[x]].y_1)||zdy(ans,x)==max(xd[tans[x]].y_0,xd[tans[x]].y_1)&&ans<tans[x])
        //ans=tans[x];
      printf("%d\n",ans);
      lastans=ans;
    }
    if(op==1)
    {
      scanf("%d%d%d%d",&x_0,&y_0,&x_1,&y_1);
      x_0=(x_0+lastans-1+mod1)%mod1+1;
      x_1=(x_1+lastans-1+mod1)%mod1+1;
      y_0=(y_0+lastans-1+mod2)%mod2+1;
      y_1=(y_1+lastans-1+mod2)%mod2+1;
      xd[++xdcnt].k=(y_1-y_0)*1.0/(x_1-x_0)*1.0;
      if(x_0<=x_1)
      {
        xd[xdcnt].x_0=x_0;
        xd[xdcnt].x_1=x_1;
        xd[xdcnt].y_0=y_0;
        xd[xdcnt].y_1=y_1;
      }
      else
      {
        xd[xdcnt].x_0=x_1;
        xd[xdcnt].x_1=x_0;
        xd[xdcnt].y_0=y_1;
        xd[xdcnt].y_1=y_0;        
      }
      if(x_0==x_1&&max(y_0,y_1)>max(xd[tans[x_0]].y_0,xd[tans[x_0]].y_1));
        tans[x_0]=xdcnt;
      if(x_0!=x_1)
        insert(1,xdcnt);
    }
  }
  return 0;
}