[李超线段树] BZOJ3165 [Heoi2013]. Segment

李超线段树裸题

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N=100010,MX=40000;

int n,lst,cnt;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

int id[N<<2];
double k[N],b[N];

inline double f(int g,int x){
  return k[g]*x+b[g];
}

inline int cover(int a,int b,int l,int r){
  double a0=f(a,l),a1=f(a,r),b0=f(b,l),b1=f(b,r);
  if(fabs(a0-b0)<1e-7 && fabs(a1-b1)<1e-7) return a<b?1:-1;
  if(a0>b0 && a1>b1) return 1;
  if(a0<b0 && a1<b1) return -1;
  return 0;
}

inline int imax(int x,int y,int z){
  if(!x) return y; if(!y) return x;
  double a=f(x,z),b=f(y,z);
  if(fabs(a-b)<1e-7) return x<y?x:y;
  return a>b?x:y;
}

void Add(int g,int l,int r,int L,int R,int x){
  int mid=L+R>>1;
  if(L==R){
    id[g]=imax(id[g],x,l); return ;
  }
  if(l==L && r==R){
    if(!id[g]) id[g]=x;
    else{
      int c=cover(id[g],x,L,R);
      if(c==1) return ;
      if(c==-1) id[g]=x;
      else{
    c=cover(id[g],x,L,mid);
    if(!c){
      if(f(x,R)>f(id[g],R)) Add(g<<1,l,mid,L,mid,id[g]),id[g]=x;
      else Add(g<<1,l,mid,L,mid,x);
    }
    else{
      if(f(x,L)>f(id[g],L)) Add(g<<1|1,mid+1,r,mid+1,R,id[g]),id[g]=x;
      else Add(g<<1|1,mid+1,r,mid+1,R,x);
    }
      }
    }
    return ;
  }
  if(r<=mid) Add(g<<1,l,r,L,mid,x);
  else if(l>mid) Add(g<<1|1,l,r,mid+1,R,x);
  else Add(g<<1,l,mid,L,mid,x),Add(g<<1|1,mid+1,r,mid+1,R,x);
}

int Query(int g,int x,int l,int r){
  if(l==r) return id[g];
  int mid=l+r>>1,ret=id[g],c;
  if(x<=mid) c=Query(g<<1,x,l,mid); else c=Query(g<<1|1,x,mid+1,r);
  return imax(ret,c,x);
}

int main(){
  read(n);
  while(n--){
    int opt; read(opt);
    if(opt){
      int a0,b0,a1,b1;
      read(a0); read(b0); read(a1); read(b1);
      a0=(a0+lst-1)%39989+1; b0=(b0+lst-1)%1000000000+1;
      a1=(a1+lst-1)%39989+1; b1=(b1+lst-1)%1000000000+1;
      if(a0>a1) swap(a0,a1),swap(b0,b1);
      ++cnt; if(a1!=a0) k[cnt]=(double)(b1-b0)/(a1-a0);
      b[cnt]=b0-k[cnt]*a0;
      Add(1,a0,a1,1,MX,cnt);
    }
    else{
      int k; read(k); k=(k+lst-1)%39989+1;
      printf("%d\n",lst=Query(1,k,1,MX));
    }
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值